思路
对于相邻的两个数 a b
区间模
p
p
p 同余
a
%
p
=
k
1
∗
x
+
c
,
b
%
p
=
k
2
∗
x
+
c
a\%p = k1*x+c , b\%p = k2*x+c
a%p=k1∗x+c,b%p=k2∗x+c 推出
(
a
−
b
)
%
p
=
k
∗
x
(a-b) \% p = k*x
(a−b)%p=k∗x
考虑差分数组,若在差分数组中一段区间
[
l
,
r
]
,
g
c
d
>
1
[l,r] ,gcd >1
[l,r],gcd>1 .则在原数组区间
[
l
−
1
,
r
]
[l-1,r]
[l−1,r] 模同一个数
x
x
x 同余
维护区间
g
c
d
gcd
gcd 可以 线段树并且可以动态维护
这里不需要修改
S
T
ST
ST 表也可维护区间
g
c
d
gcd
gcd
如何枚举答案?
暴力枚举不可取,由于区间
g
c
d
gcd
gcd 具有单调性,可以二分 也可以
枚举右端点
r
r
r,然后移动左端点
l
l
l
代码
#define int long long
#define endl "\n"
#define _orz ios::sync_with_stdio(false),cin.tie(0)
#define mem(str,num) memset(str,num,sizeof(str))
#define forr(i,a,b) for(int i = a; i <= b;i++)
#define forn(i,n) for(int i = 0; i < n; i++)
#define dbg() cout <<"0k!"<< endl;
typedef long long ll;
int pri[16] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
const int inf = 0x3f3f3f3f;
const int INF = ~0ULL;
const int N = 1e6+10;
int a[200005],b[200005];
// struct node{
// int l,r;
// int dat;
// #define ls i<<1
// #define rs i<<1|1
// }t[200005<<2];
// void build(int i,int l,int r){
// t[i].l = l,t[i].r = r;
// if(l==r){
// t[i].dat = b[l];
// return;
// }
// int mid = (l+r) >> 1;
// build(ls,l,mid);
// build(rs,mid+1,r);
// t[i].dat = __gcd(t[ls].dat,t[rs].dat);
// }
// int ask(int i,int l,int r){
// if(l <= t[i].l && r >= t[i].r){
// return t[i].dat;
// }
// int res = 0;
// int mid = (t[i].l+t[i].r)>>1;
// if(l <= mid) res = __gcd(res,ask(ls,l,r));
// if(r >mid ) res = __gcd(res,ask(rs,l,r));
// return abs(res);
// }
int f[200005][21];
int n;
void ST(){
// 不用初始化
forr(i,1,n) f[i][0] = b[i];
forr(i,1,20)for(int j = 1;j+(1<<i)-1 <= n;j++){
f[j][i] = __gcd(f[j][i-1],f[j+(1<<(i-1))][i-1]);
}
}
void solve(){
cin>>n;
forr(i,1,n) cin>> a[i],b[i] = abs(a[i]-a[i-1]);
ST();
if(n==1){
cout << 1 << endl;
return;
}
//build(1,1,n);
int l = 2; // 细节点 因为差分数组b[1]与原数组相同 所以我们要从l=2开始枚举,因为有时会出现b[1]可能会在提供答案的区间内导致答案+1,例如样例2
int res = 1;
for(int r = 2;r <= n;r++){
if(b[r]==1) continue;
while(l < r){
int len =__lg(r-l+1);
if(__gcd(f[r-(1<<len)+1][len],f[l][len]) == 1) l++;
else break;
}
res = max(res,r-l+2);
}
cout << res << endl;
}
signed main()
{
_orz;
int t;cin>>t;
while(t--) solve();
return 0;
}