L. Coordinate Paper
构造一个长度为nnn的序列aaa,满足ai≥0a_i \geq 0ai≥0,∑i=1nai=s\sum\limits_{i = 1} ^{n} a_i = si=1∑nai=s,对于任意的i∈[1,n−1]i \in [1, n - 1]i∈[1,n−1],都有ai−ai+1=korai+1−ai=1a_i - a_{i + 1} = k\ or\ a_{i + 1} - a{i} = 1ai−ai+1=k or ai+1−ai=1,其中n,s,kn, s, kn,s,k是给定的数。
假定所有的aia_iai都满足ai+1−ai=1a_{i + 1} - a_{i} = 1ai+1−ai=1,则对于一个给定的a1a_1a1,有∑i=1nai=n×a1+n(n−1)2\sum\limits_{i = 1} ^{n} a_i = n \times a_1 + \frac{n(n - 1)}2i=1∑nai=n×a1+2n(n−1),考虑ai−ai+1=ka_i - a_{i + 1} = kai−ai+1=k,∑i=1nai=n×a1+n(n−1)2−x(k+1)\sum\limits_{i = 1} ^{n} a_i = n \times a_1 + \frac{n(n - 1)}2- x (k + 1)i=1∑nai=n×a1+2n(n−1)−x(k+1)。
考虑对所有数(modk+1)\pmod {k + 1}(modk+1)下找到一个解,满足∑i=1nai(modk+1)≡s(modk+1)\sum\limits_{i = 1} ^{n} a_i \pmod {k + 1} \equiv s \pmod {k + 1}i=1∑nai(modk+1)≡s(modk+1)。
考虑同余下的一个最小解,a1,a1+1,…,k,0,1,2,…,k,0,1,2,…a_1, a_1 + 1, \dots, k, 0, 1, 2, \dots, k, 0, 1, 2, \dotsa1,a1+1,…,k,0,1,2,…,k,0,1,2,…,如果满足sum≤sandsum(modk+1)≡s(modk+1)sum \leq s \ and\ sum \pmod{k + 1} \equiv s \pmod{k + 1}sum≤s and sum(modk+1)≡s(modk+1),则说明找到一组解。
获得最小解后,凑得答案,只需每次对最小得加k+1k + 1k+1,这样可以保证变动之后这个数比其前方的大111,后面的比其小kkk,满足要求。
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;int n, k, flag;long long s, a[N];vector<int> pos[N];inline int add(int x, int y) {return x + y < k + 1 ? x + y : x + y - k - 1;
}void solve() {for (int i = 1; i <= n; i++) {a[i] = add(a[i - 1], i != 1);pos[a[i]].push_back(i);}int x = a[1], len = min(k - x + 1, n), last = n - len;long long sum = 1ll * (x + x + len - 1) * len / 2;sum += 1ll * (last / (k + 1)) * (0 + k) * (k + 1) / 2;last %= k + 1;sum += 1ll * (0 + 0 + last - 1) * last / 2;s -= sum;sum = s / (k + 1);long long tot = sum / n, more = sum % n;for (int i = 1; i <= n; i++) {a[i] += 1ll * (k + 1) * tot;}for (int i = 0; i <= k; i++) {for (auto it : pos[i]) {if (more) {a[it] += k + 1;more--;}}}for (int i = 1; i <= n; i++) {printf("%lld%c", a[i], i == n ? '\n' : ' ');}
}bool judge(int x) {int len = min(k - x + 1, n), last = n - len;long long sum = 1ll * (x + x + len - 1) * len / 2;sum += 1ll * (last / (k + 1)) * (0 + k) * (k + 1) / 2;last %= k + 1;sum += 1ll * (0 + 0 + last - 1) * last / 2;return sum <= s && s % (k + 1) == sum % (k + 1);
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);cin >> n >> k >> s;for (int i = 0; i <= k; i++) {if (judge(i)) {flag = 1;a[0] = i;solve();break;}}if (!flag) {puts("-1");}return 0;
}