题目链接
题目大意
给定三个正整数 n , a , k n, a, k n,a,k,其中:
- n n n 为怪物的数量, n n n 个怪物站成一排,从左到右编号 1 1 1 到 n n n;
- a a a 为 n n n 个怪物的血量和,且每个怪物的血量都是正数;
- k k k 为小苯的操作次数。
每次操作,小红会选择一个或相邻两个怪物,使得它(们)的血量(各自) − 1 -1 −1。当怪物的血量 ≤ 0 \leq 0 ≤0 时,怪物被消灭(相邻关系不会改变)。
小红一定会选择最优策略,使用尽可能少的攻击次数消灭这些怪物。
在这种情况下,小苯希望小红能使用恰好 k k k 次攻击消灭所有的怪物。
请你帮小苯找出一个可能的血量分配方案,如果不行输出 − 1 -1 −1。
数据范围
- 1 ≤ n ≤ 2 ⋅ 1 0 5 , 1 \leq n \leq 2 \cdot 10^5, 1≤n≤2⋅105,
- n ≤ a ≤ 1 0 9 , n \leq a \leq 10^9, n≤a≤109,
- 1 ≤ k ≤ 1 0 9 . 1 \leq k \leq 10^9. 1≤k≤109.
Solution
首先, n = 1 n = 1 n=1 时,只能将 a a a 分配给一个怪物,所以只要看是否有 a = k a = k a=k。
下面考虑 n > 1 n > 1 n>1 的情况。
由于需要恰好 k k k 次操作,所以我们需要找到操作次数的上下界。
先找下界 L L L。
- 要想操作次数接近下界 L L L,就要尽可能让小红选择相邻两个怪物一起扣血;
- 首先为每个怪物分配 1 1 1 生命值,这样还剩下 a − n a - n a−n 的血量和;
- 然后我们再分配 ⌊ a − n 2 ⌋ \left\lfloor \dfrac{a - n}{2} \right\rfloor ⌊2a−n⌋ 给怪物 1 1 1,分配 ⌈ a − n 2 ⌉ \left\lceil \dfrac{a - n}{2} \right\rceil ⌈2a−n⌉ 给怪物 2 2 2。
- 当 n n n 是偶数,
- 小红先通过 n 2 \dfrac{n}{2} 2n 次操作消除下面分配的 1 1 1 生命值,然后再通过 ⌈ a − n 2 ⌉ \left\lceil \dfrac{a - n}{2} \right\rceil ⌈2a−n⌉ 次操作消灭怪物 1 1 1 和 2 2 2;
- 操作次数为 n 2 + ⌈ a − n 2 ⌉ = ⌈ a 2 ⌉ \dfrac{n}{2} + \left\lceil \dfrac{a - n}{2} \right\rceil = \left\lceil \dfrac{a}{2} \right\rceil 2n+⌈2a−n⌉=⌈2a⌉;
- 当 n n n 是奇数,
- 小红先通过 ⌈ n 2 ⌉ \left\lceil \dfrac{n}{2} \right\rceil ⌈2n⌉ 次操作消除下面分配的 1 1 1 生命值,这时会影响到怪物 2 2 2 的血量会提前 − 1 -1 −1,变为 ⌈ a − n 2 ⌉ − 1 ≤ ⌊ a − n 2 ⌋ \left\lceil \dfrac{a - n}{2} \right\rceil - 1 \leq \left\lfloor \dfrac{a - n}{2} \right\rfloor ⌈2a−n⌉−1≤⌊2a−n⌋,所以再通过 ⌊ a − n 2 ⌋ \left\lfloor \dfrac{a - n}{2} \right\rfloor ⌊2a−n⌋ 次操作就能消灭怪物 1 1 1 和 2 2 2;
- 操作次数为 ⌈ n 2 ⌉ + ⌊ a − n 2 ⌋ = ⌊ n + 1 2 ⌋ + ⌊ a − n 2 ⌋ = ⌊ a + 1 2 ⌋ = ⌈ a 2 ⌉ \left\lceil \dfrac{n}{2} \right\rceil + \left\lfloor \dfrac{a - n}{2} \right\rfloor = \left\lfloor \dfrac{n + 1}{2} \right\rfloor + \left\lfloor \dfrac{a - n}{2} \right\rfloor = \left\lfloor \dfrac{a + 1}{2} \right\rfloor = \left\lceil \dfrac{a}{2} \right\rceil ⌈2n⌉+⌊2a−n⌋=⌊2n+1⌋+⌊2a−n⌋=⌊2a+1⌋=⌈2a⌉;
- 这样就说明操作次数下界 L = ⌈ a 2 ⌉ L = \left\lceil \dfrac{a}{2} \right\rceil L=⌈2a⌉。
再找上界 R R R。
- 要想操作次数接近上界 R R R,就要尽可能让小红只选择一个怪物扣血;
- 首先为每个怪物分配 1 1 1 生命值,这样还剩下 a − n a - n a−n 的血量和;
- 然后我们直接给怪物 1 1 1 分配 a − n a - n a−n 的血量。
- 当 n n n 是偶数,
- 小红先通过 n 2 \dfrac{n}{2} 2n 次操作消除下面分配的 1 1 1 生命值,然后再通过 a − n a - n a−n 次操作消灭怪物 1 1 1;
- 操作次数为 n 2 + ( a − n ) = a − n 2 = a − ⌊ n 2 ⌋ \dfrac{n}{2} + (a - n) = a - \dfrac{n}{2} = a - \left\lfloor \dfrac{n}{2} \right\rfloor 2n+(a−n)=a−2n=a−⌊2n⌋;
- 当 n n n 是奇数,
- 小红先通过 ⌈ n 2 ⌉ \left\lceil \dfrac{n}{2} \right\rceil ⌈2n⌉ 次操作消除下面分配的 1 1 1 生命值,这时怪物 1 1 1 不受影响,还剩 a − n a - n a−n 的血量值,我们再通过 a − n a - n a−n 次操作消灭怪物 1 1 1;
- 操作次数为 ⌈ n 2 ⌉ + ( a − n ) = a − ⌊ n 2 ⌋ \left\lceil \dfrac{n}{2} \right\rceil + (a - n) = a - \left\lfloor \dfrac{n}{2} \right\rfloor ⌈2n⌉+(a−n)=a−⌊2n⌋;
- 这样就说明操作次数上界 R = a − ⌊ n 2 ⌋ R = a - \left\lfloor \dfrac{n}{2} \right\rfloor R=a−⌊2n⌋。
所以只有当 ⌈ a 2 ⌉ ≤ k ≤ a − ⌊ n 2 ⌋ \left\lceil \dfrac{a}{2} \right\rceil \leq k \leq a - \left\lfloor \dfrac{n}{2} \right\rfloor ⌈2a⌉≤k≤a−⌊2n⌋ 时,才有可能构造一个合法分配。
考虑从上界 R = a − ⌊ n 2 ⌋ R = a - \left\lfloor \dfrac{n}{2} \right\rfloor R=a−⌊2n⌋ 开始调整。
此时怪物 1 1 1 除了底部的 1 1 1 血量值,还有额外分配的 a − n a - n a−n 血量值,我们将其拿出 s s s 来分配给怪物 2 2 2,这样怪物 1 1 1 的额外血量为 a − n − s a - n - s a−n−s,怪物 2 2 2 的额外血量为 s s s。
接着考虑这种分配下的操作次数。
- 当 n n n 是偶数,需要满足 a − n − s ≥ s a - n - s \geq s a−n−s≥s,即 s ≤ ⌊ a − n 2 ⌋ s \leq \left\lfloor \dfrac{a - n}{2} \right\rfloor s≤⌊2a−n⌋;
- 小红先通过 n 2 \dfrac{n}{2} 2n 次操作消除下面分配的 1 1 1 生命值,然后再通过 a − n − s a - n - s a−n−s 次操作消灭怪物 1 1 1 和 2 2 2;
- 操作次数为 n 2 + ( a − n − s ) = a − n 2 − s = a − ⌊ n 2 ⌋ − s \dfrac{n}{2} + (a - n - s) = a - \dfrac{n}{2} - s = a - \left\lfloor \dfrac{n}{2} \right\rfloor- s 2n+(a−n−s)=a−2n−s=a−⌊2n⌋−s;
- 当 n n n 是奇数,需要满足 a − n − s ≥ s − 1 a - n - s \geq s - 1 a−n−s≥s−1,即 s ≤ ⌊ a − n + 1 2 ⌋ = ⌈ a − n 2 ⌉ s \leq \left\lfloor \dfrac{a - n + 1}{2} \right\rfloor = \left\lceil\dfrac{a - n}{2} \right\rceil s≤⌊2a−n+1⌋=⌈2a−n⌉;
- 小红先通过 ⌈ n 2 ⌉ \left\lceil \dfrac{n}{2} \right\rceil ⌈2n⌉ 次操作消除下面分配的 1 1 1 生命值,这时怪物 2 2 2 受到影响,还剩 s − 1 s - 1 s−1 的血量值,我们再通过 a − n − s a - n - s a−n−s 次操作消灭怪物 1 1 1 和 2 2 2;
- 操作次数为 ⌈ n 2 ⌉ + ( a − n − s ) = a − ⌊ n 2 ⌋ − s \left\lceil \dfrac{n}{2} \right\rceil + (a - n - s) = a - \left\lfloor \dfrac{n}{2} \right\rfloor - s ⌈2n⌉+(a−n−s)=a−⌊2n⌋−s;
综上,操作次数为 a − ⌊ n 2 ⌋ − s a - \left\lfloor \dfrac{n}{2} \right\rfloor - s a−⌊2n⌋−s。
于是令 k = a − ⌊ n 2 ⌋ − s k = a - \left\lfloor \dfrac{n}{2} \right\rfloor- s k=a−⌊2n⌋−s,得到 s = a − ⌊ n 2 ⌋ − k . s = a - \left\lfloor \dfrac{n}{2} \right\rfloor - k. s=a−⌊2n⌋−k.
接下来只要验证这个解是否满足条件。
- 当 n n n 为偶数,需要满足 s ≤ ⌊ a − n 2 ⌋ s \leq \left\lfloor \dfrac{a - n}{2} \right\rfloor s≤⌊2a−n⌋;
- 当 a a a 为偶数,左式 s = a − n 2 − k s = a - \dfrac{n}{2} - k s=a−2n−k,右式 a − n 2 \dfrac{a - n}{2} 2a−n,作差得到 a 2 − k = ⌈ a 2 ⌉ − k ≤ 0 \dfrac{a}{2} - k = \left\lceil \dfrac{a}{2} \right\rceil - k \leq 0 2a−k=⌈2a⌉−k≤0
- 当 a a a 为奇数,左式 a − n 2 − k a - \dfrac{n}{2} - k a−2n−k,右式 a − n − 1 2 \dfrac{a - n - 1}{2} 2a−n−1,作差得到 a + 1 2 − k = ⌈ a 2 ⌉ − k ≤ 0 \dfrac{a + 1}{2} - k = \left\lceil \dfrac{a}{2} \right\rceil - k \leq 0 2a+1−k=⌈2a⌉−k≤0;
- 当 n n n 为奇数,需要满足 s ≤ ⌈ a − n 2 ⌉ s \leq \left\lceil\dfrac{a - n}{2} \right\rceil s≤⌈2a−n⌉;
- 当 a a a 为奇数,左式 a − n − 1 2 − k a - \dfrac{n - 1}{2} - k a−2n−1−k,右式 a − n 2 \dfrac{a - n}{2} 2a−n,作差得到 a + 1 2 − k = ⌈ a 2 ⌉ − k ≤ 0 \dfrac{a + 1}{2} - k = \left\lceil \dfrac{a}{2} \right\rceil - k \leq 0 2a+1−k=⌈2a⌉−k≤0;
- 当 a a a 为偶数,左式 a − n − 1 2 − k a - \dfrac{n - 1}{2} - k a−2n−1−k,右式 a − n + 1 2 \dfrac{a - n + 1}{2} 2a−n+1,作差得到 a 2 − k = ⌈ a 2 ⌉ − k ≤ 0 \dfrac{a}{2} - k = \left\lceil \dfrac{a}{2} \right\rceil - k \leq 0 2a−k=⌈2a⌉−k≤0;
综上,解 s = a − ⌊ n 2 ⌋ − k s = a - \left\lfloor \dfrac{n}{2} \right\rfloor - k s=a−⌊2n⌋−k 合法。
那么额外分配给怪物 1 1 1 的为 a − n − s = k − ⌈ n 2 ⌉ a - n - s = k - \left\lceil \dfrac{n}{2} \right\rceil a−n−s=k−⌈2n⌉,怪物 2 2 2 的为 a − ⌊ n 2 ⌋ − k a - \left\lfloor \dfrac{n}{2} \right\rfloor - k a−⌊2n⌋−k。
C++ Code
cpp
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, a, k;
std::cin >> n >> a >> k;
if (n == 1) {
std::cout << (a == k ? a: -1) << "\n";
return 0;
}
if ((a + 1) / 2 > k or a - n / 2 < k) {
std::cout << -1 << "\n";
return 0;
}
std::vector ans(n, 1);
ans[0] += k - (n + 1) / 2;
ans[1] += a - k - n / 2;
for (int i = 0; i < n; i++) {
std::cout << ans[i] << " \n"[i == n - 1];
}
return 0;
}