根据数学常识(裴蜀定理),能用这些步长组合跳出的最小正距离,就是它们的最大公约数(GCD)。
我们令 g = \gcd(2d_1, 2d_2, \dots, 2d_{n-1})。
第二个结论:无论怎么操作,a_1 每次变动的值一定是 g 的整数倍。
最终的 a_1 必须满足:
a'_1 \equiv a_1 \pmod g
为什么调整 a_1 不会影响最终单调性?
你肯定担心调整 a_1 的过程(使用前缀操作)可能会把后面的差分变成负数。
实际上并不影响,后面的负数可以逐个调整。
前面分析过,对后缀操作**只会翻转后面的差分,绝对不会影响前面的元素**。所以这样做不仅能把所有差分全部翻正,还绝对不会动到我们已经固定好的 $a_1$。
## 代码
根据思路,可以写出简短的代码:
1. 算出所有原差分的绝对值 $|d_i|$,并求和记为 `sum_d`。
2. 算出所有 $|d_i|$ 的最大公约数,并乘 $2$,记为步长 `g`。
3. 把原 $a_1$ 在步长 `g` 的限制下,缩小到 $\ge 1$ 的最小值,再加上 `sum_d` 即为答案。
```cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
long long a[N];
int main()
{
cin.tie(0)->sync_with_stdio(0);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
long long sum_d = 0;
long long g = 0;
for (int i = 1; i < n; i++)
{
long long d = abs(a[i + 1] - a[i]);
sum_d += d;
g = __gcd(g, d);
}
g *= 2;
long long v1;
if (g == 0) // 如果所有元素原本就相等,步长为 0,a1 无法改变
v1 = a[1];
else
v1 = ((a[1] - 1) % g + g) % g + 1;
cout << v1 + sum_d << "\n";
return 0;
}
```