题目核心思路解析
这里是题目链接
1. 操作的本质与等差数列的性质
题目允许我们对数组中的元素进行任意次“加 $x$”或“减 $x$”的操作。这意味着,最终数组中的每个元素 $a_i$ 都可以变成 $a_i + k \cdot x$($k$ 为任意整数)。
换句话说,每个元素在模 $x$ 意义下的余数是不会改变的。
假设我们最终将数组变成了一个公差为 $D$ 的等差数列,那么对于任意相邻的两个元素,它们的差值在模 $x$ 意义下必须等于 $D$。
即:$a_{i+1} - a_i \equiv D \pmod x$。
2. 推导关键约束条件
既然所有的相邻差值 $a_{i+1} - a_i$ 在模 $x$ 意义下都等于 $D$,那么任意两个相邻差值在模 $x$ 意义下必须相等。
即:$(a_{i+1} - a_i) \equiv (a_{j+1} - a_j) \pmod x$。
将其转化为整除关系,即:$x$ 必须能整除任意两个相邻差值的差。
即:$x \mid ((a_{i+1} - a_i) - (a_{j+1} - a_j))$。
为了让 $x$ 尽可能大,我们需要找到所有“相邻差值的差”的最大公约数(GCD)。
完整代码
#include<bits/stdc++.h>
using namespace std;
long long my_gcd(long long a, long long b) {
a = abs(a);
b = abs(b);
while (b != 0) {
a %= b;
swap(a, b);
}
return a;
}
int main() {
int n;
if (!(cin >> n)) return 0;
vector<long long> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
bool is_arithmetic = true;
if (n >= 2) {
long long diff = a[1] - a[0];
for (int i = 2; i < n; ++i) {
if (a[i] - a[i-1] != diff) {
is_arithmetic = false;
break;
}
}
}
if (is_arithmetic) {
cout << -1 << endl;
return 0;
}
long long base_diff = a[1] - a[0];
long long gcd_val = 0;
for (int i = 2; i < n; ++i) {
long long current_diff = a[i] - a[i-1];
long long val = current_diff - base_diff;
gcd_val = my_gcd(gcd_val, val);
}
cout << gcd_val << endl;
return 0;
}
评论 (0)