#数论 #枚举 #gcd
Given an integer sequence a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an of length n n n and a non-negative integer k k k, you can perform the following operation at most once: Choose two integers l l l and r r r such that 1 ≤ l ≤ r ≤ n 1 \le l \le r \le n 1≤l≤r≤n, then for each l ≤ i ≤ r l \le i \le r l≤i≤r, change a i a_i ai into ( a i + k ) (a_i + k) (ai+k).
Maximize the greatest common divisor of the whole sequence.
An integer g g g is said to be the common divisor of the whole sequence, if a i a_i ai is divisible by g g g for all 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n.
There are multiple test cases. The first line of the input contains an integer T T T indicating the number of test cases. For each test case:
The first line contains two integers n n n and k k k ( 1 ≤ n ≤ 3 × 1 0 5 1\leq n\leq 3 \times 10^5 1≤n≤3×105, 0 ≤ k ≤ 1 0 18 0\leq k\leq 10^{18} 0≤k≤1018).
The second line contains n n n integers a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an ( 1 ≤ a i ≤ 1 0 18 1 \le a_i \le 10^{18} 1≤ai≤1018) indicating the sequence.
It’s guaranteed that the sum of n n n of all test cases does not exceed 3 × 1 0 5 3 \times 10^5 3×105.
For the first sample test case, choose l = 2 l = 2 l=2 and r = 4 r = 4 r=4. The sequence will become { 5 , 5 , 15 , 10 , 10 , 555 } \{5, 5, 15, 10, 10, 555\} {5,5,15,10,10,555}. Its greatest common divisor is 5 5 5.
2
6 2
5 3 13 8 10 555
3 0
3 6 9
5
3
首先我们处理出 b b b数组,其中 b i : = a i + k b_i:=a_i+k bi:=ai+k,我们就能将问题转换为另一个问题:选择 b i b_i bi中的区间 [ l , r ] [l,r] [l,r],使用 [ b l , b r ] [b_l,b_r] [bl,br]替换 a a a中的 [ a l , a r ] [a_l,a_r] [al,ar](可以不换),求这样最大值。
显然,我们可以枚举右端点,由于前缀 g c d gcd gcd只有 l o g 2 n log_2n log2n种,因此我们可以使用 s t d : : s e t std::set std::set直接存入所有可能的交换组合,就能枚举出所有的情况了。
而对于后缀我们直接就预处理一个后缀 g c d gcd gcd即,答案就是 min r = 1 r ≤ n ( min ( gcd ( x , s a r + 1 ) x ∈ s e t ) ) \min_{r =1}^{r\leq n}(\min(\gcd(x,sa_{r+1})\ x\in set)) minr=1r≤n(min(gcd(x,sar+1) x∈set)),
整体时间复杂度在 n l o g 2 n nlog^2n nlog2n,包括 g c d gcd gcd的 l o g 2 n log_2n log2n。
void solve() {
int n, k;
std::cin >> n >> k;
std::vector<int>a(n + 1), pa(n + 2), sa(n + 2);
for (int i = 1; i <= n; ++i) {
std::cin >> a[i];
pa[i] = std::gcd(pa[i - 1], a[i]);
}
std::vector<int>b(n + 1);
for (int i = 1; i <= n; ++i) {
b[i] = a[i] + k;
}
for (int i = n; i; --i) {
sa[i] = std::gcd(sa[i + 1], a[i]);
}
int ans = pa[n];
std::set<int>st[2];
for (int r = 1; r <= n; ++r) {
int now = r & 1, lst = now ^ 1;
for (auto& x : st[lst]) {
int t = std::gcd(x, b[r]);
st[now].insert(t);
}
int t = std::gcd(pa[r - 1], b[r]);
st[now].insert(t);
st[lst].clear();
for (auto& x : st[now]) {
int w = std::gcd(x, sa[r + 1]);
ans = std::max(ans, w);
}
}
std::cout << ans << "\n";
}
signed main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t--) {
solve();
}
}