2025暑期牛客6

遇到gcd要考虑相邻元素之差,gcd(a1,a2...an)=gcd(a1,a1-a2,a2-a3...an-an-1)
强行记住分类讨论:一个是全局都进行加,另一个是部分加,那么头和尾至少有一个不会加,所以要单独考虑首尾,即分类讨论a[0]的因子和a[n-1]的因子然后和剩下的元素gcd的因子
using namespace std;
using ll = long long;
const int N = 1e5 + 8;
vector<vector<int>> fac(N); // 预处理因子表
// 预处理所有数的因子(1~N-1)
void precompute_factors() {
for (int i = 1; i < N; ++i)
for (int j = i; j < N; j += i)
fac[j].push_back(i);
}
// 通用检查函数:枚举因子列表,返回最大有效因子
ll check_factors(const vector<int>& factors, const vector<ll>& a) {
int n = a.size();
ll max_d = 1; // 初始最大因子为1
for (int x : factors) { // 遍历每个因子x
vector<ll> mod(n);
for (int i = 0; i < n; ++i)
mod[i] = a[i] % x; // 计算每个元素模x的余数
// 检查所有非0余数是否相同
int f = -1;
bool valid = true;
for (int m : mod) {
if (m != 0) {
if (f == -1) f = m;
else if (f != m) { valid = false; break; }
}
}
if (!valid) continue;
// 所有余数为0:直接有效
if (f == -1) {
max_d = max((ll)x, max_d);
continue;
}
// 检查非0余数是否为连续一段
int cnt = 0; // 连续段数量
int pre = -1; // 上一个余数
for (int m : mod) {
if (m == f && pre != f) cnt++;
pre = m;
}
if (cnt == 1) // 仅一段连续非0余数,有效
max_d = max((ll)x, max_d);
}
return max_d;
}
void solve() {
int n;
cin >> n;
vector<ll> a(n);
bool all_same = true;
for (int i = 0; i < n; ++i) {
cin >> a[i];
if (a[i] != a[0]) all_same = false;
}
// 特殊情况:所有元素相等
if (all_same) {
cout << 0 << '\n';
return;
}
// 1. 检查a[0]的因子
ll ans = check_factors(fac[a[0]], a);
// 2. 检查a[n-1]的因子
ans = max(ans, check_factors(fac[a.back()], a));
// 3. 检查相邻元素差的GCD的因子
vector<ll> sorted_a = a;
sort(sorted_a.begin(), sorted_a.end());
ll d = 0;
for (int i = 1; i < n; ++i)
d = gcd(d, sorted_a[i] - sorted_a[i-1]);
ans = max(ans, check_factors(fac[d], a));
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
precompute_factors(); // 预处理因子表
int T;
cin >> T;
while (T--) solve();
return 0;
}