AT_arc079_b [ABC068D] Decrease (Contestant ver.) 题解
AT_arc079_b [ABC068D] Decrease (Contestant ver.) 题解
简化题意
构造一个长度为 \(n\) 的序列 \(\{a\}\),我们希望对其进行若干次操作,每次操作如下:
找到数列中最大的一个数 \(a_i\),若有重复任选其一。对其执行 \(a_i \rightarrow a_i - n\);且对于所有 \(1 \leq j \leq n\),\(j \neq i\) 执行 \(a_j \rightarrow a_j + 1\)。
我们希望总共进行的操作次数为 \(k\),请构造一个满足上述条件的序列 \(\{a\}\)。
且 \(a_i\)、\(n\) 需要满足:\(2 \leq n \leq 50\),\(0 \leq a_i \leq 10 ^ {16} + 1000\)(\(1 \leq i \leq n\))。
解题思路
这个数据范围非常的大,肯定不能暴力;我们考虑先观察一下规律。
这里考虑直接用 \(n = 50\) 的情况来构造,方便大数据的操作。
我们借助几个样例,来具体看看该怎么实现。
- \(k = 0\)
构造方案:
50
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
我们可以发现,此时的答案是 \(0\) 到 \(49\) 的递增序列。
- \(k = 1\)
构造方案:
50
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 50
此时我们可以得出一个结论:如果我们希望改变序列,使原来的操作次数 \(+1\)(即 \(k + 1\)),那么需要进行的操作就是:找到目前最近的一个 \(i\) 满足 \(a_i + 2 = a_{i + 1}\)(若没有,则 \(i = 50\)),执行 \(a_i \rightarrow a_i + 1\)。
- \(k = 50\)
构造方案:
50
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
此时,我们发现,整个序列,由 \(k = 0\) 的情况全体都 \(+1\)。因此,我们发现:\(k\) 每大 \(50\),全体 \(a_i\) 都 \(+1\)。
这样,大家是否能发现规律呢?没错!一开始(指 \(k = 0\) 时),序列 \(a = \{0, 1, 2, \cdots , 49\}\)。
而 \(k\) 每增加 \(50\),整个序列就全体 \(+1\);设剩余的 \(k\) 为 \(k'\),我们将 \(a_{50} \sim a_{50 - k'}\) 再全部 \(+1\) 即可。
根据上述的操作,不难发现,\(k' = k \bmod 50\),全体序列 \(+1\) 的次数等于 \(\frac{k}{50}\) 吧。
这样利用倒推,我们就可以高效的求出序列 \(\{a\}\) 了。
代码部分
#include <bits/stdc++.h>
using namespace std;
long long n;
long long a[100];
int main()
{
//freopen("decrease.in", "r", stdin);
//freopen("decrease.out", "w", stdout);
cin >> n;
for(int i = 1;i <= 50;i ++)//一开始的序列是 0, 1, 2,...49.
a[i] = i - 1;
long long p = n % 50, q = n / 50;//q 记录一开始所有数要 +1 的次数;p 相当于上文中的 k'
for(int i = 1;i <= 50;i ++)//全都要增加 q
a[i] += q;
for(int i = 1;i <= p;i ++)//尾部的 a 要全部 +1
a[50 - i + 1] ++;
cout << 50 << "\n";
for(int i = 1;i <= 50;i ++)
cout << a[i] << " ";
return 0;
}
浙公网安备 33010602011771号