题解 CF1409C 【Yet Another Array Restoration】

Suuon_Kanderu

2020-09-10 21:42:00

Solution

这题还是比较简单的,算是个模拟。 做这种题最重要的是思路清晰,现在真是颓废刷这种毫无思维含量的题还要 WA 一次。 思路: 1. 题目要求一个等差数列,我的思路是枚举公差。因为 $x,y \in {a_i}$ ,公差的取值范围是 $[1 , y - x]$ , 超过 $y-x$ 肯定无法同时包含 $x$ 和 $y$。 2. 如果公差 $d$ 不是 $y-x$ 的因数,显然不满足条件。直接排除。然后我们假设现在的序列为 $ x ~,~ x + d ~,~ x + 2 \cdot d \cdots ~, ~y~$,此时序列长度 $len$ 为 $\frac{y-x} d + 1$。 3. 如果此时的 $len$ 已经超过了 $n$ 项,直接跳过。 3. 此时分情况讨论哪些满足条件,并记录答案: 1. 按照贪心,我们先向左边扩展一些,变成 $\cdots x - 2 \cdot d ~,~ x-d,~ x ~,~ x + d ~,~ x + 2 \cdot d \cdots ~, ~y~$。发现左边最多能够扩展 $\frac{x-1}{d}$ 个数。如果只要左边扩展或者不扩展就有 $\mathcal {n}$ 项,即 $len = \frac{y-x} d + 1 + \frac{x-1}{d} \ge n$。此时数列中的最大值为 $y$。 2. 如果还不够,我们只好向右扩展了。向右扩展 $n-len$项。此时数列中最大值为 $y + (n - cnt) \cdot d $ 。 代码就很简单了,理顺逻辑即可,细节较多。 ```cpp #include <cstdio> #include <algorithm> #include <cmath> #include <cstdlib> #include <cstring> typedef long long ll; const int N = 200000+100; void work(int x , int y , int n) { int ans = 0x7fffffff , d; for(int i = 1; i <= y - x; i++) { if(!((y - x) % i == 0))continue; int cnt = 0;//即为 len cnt += (y - x) / i + 1; if(cnt > n)continue; cnt += (x - 1) / i; if( cnt >= n) { if(y < ans)ans = y , d = i; }else { if(y + (n - cnt) * i < ans) ans = y + (n - cnt) * i , d = i; } } for(int i = 1; i <= n; i++)printf("%d " , ans) , ans -= d; puts(""); } int main() { int t;scanf("%d" , &t); while(t--) { int x , y , n; scanf("%d%d%d" , &n , &x , &y); work(x , y , n); }return 0; } ```