很容易发现满足题目要求的区间长度是符合二分性质的,即如果长度为len的[l, r]可行,那么一定至少存在一个长度为len-1的子区间[l+1, r]或[l, r-1]可行
所以就对长度进行二分答案
接下来的问题是如何判断一个区间是否符合要求
首先发现如果存在一个 aj 可以被 a[l,r] 中的所有元素整除,那么它一定是这个区间的最小值,并且它还是这个区间的所有元素的gcd
所以问题就转化成了区间查询最小值和gcd,如果一个区间的最小值和区间gcd相等,那么这个区间就符合条件
区间最小值比较好处理,那么区间gcd呢,其实求区间gcd就是在求区间内所有数对某个质因子的指数求最小(可以用算数基本原理模拟一下),本质上还是在求区间最小值
所以区间gcd和区间最小值一样具有可区间合并的性质,即min(min(l1, r1), min(l2, r2))=min(l1, r2) gcd(gcd(l1, r1), gcd(l2, r2))=gcd(l1, r2) (l1<=r1, l2<=r2)
由于只涉及到查询操作,所以可以用st表处理
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define db double
#define rep(x,a,b) for(int x=(a);x<=(b);x++)
#define per(x,a,b) for(int x=(a);x>=(b);x--)
#define reP(x,a,b) for(int x=(a);x<(b);x++)
#define Per(x,a,b) for(int x=(a);x>(b);x--)
#define scf(a) scanf("%d",&a)
#define scfll(a) scanf("%lld",&a)
#define scfdb(a) scanf("%lf",&a)
#define ptf(a) printf("%d",a)
#define ptfll(a) printf("%lld",a)
#define ptfsp(a) printf("%d ",a)
#define ptfllsp(a) printf("%lld ",a)
#define pli(a,b) make_pair(a,b)
#define pb push_back
#define el puts("")
#define FS first
#define SE second
#define PI acos(-1)
#define ls pos<<1
#define rs pos<<1|1
/*ios::sync_with_stdio(false);
freopen("in.txt","r",stdin);
freopen("1.out","w",stdout);*/
using namespace std;
const ll mod=998244353;
const int maxn=3e5+5;
int stgcd[maxn][20],stmin[maxn][20],lg2[maxn],n;
int getgcd(int l,int r){
int j=lg2[r-l+1];
return __gcd(stgcd[l][j],stgcd[r-(1<<j)+1][j]);
}
int getmin(int l,int r){
int j=lg2[r-l+1];
return min(stmin[l][j],stmin[r-(1<<j)+1][j]);
}
bool check(int mid){
rep(i,1,n){
int j=i+mid-1;
if(j>n) break;
if(getgcd(i,j)==getmin(i,j)) return 1;
}
return 0;
}
int ans[maxn],Ans,cnt;
int main(){
scf(n);
lg2[1]=0;
rep(i,2,n) lg2[i]=lg2[i>>1]+1;
rep(i,1,n){
int x;scf(x);
stgcd[i][0]=stmin[i][0]=x;
}
for(int j=1;j<=19;j++){
rep(i,1,n){
if(i+(1<<j-1)>n) break;
stgcd[i][j]=__gcd(stgcd[i][j-1],stgcd[i+(1<<j-1)][j-1]);
stmin[i][j]=min(stmin[i][j-1],stmin[i+(1<<j-1)][j-1]);
}
}
int l=1,r=n,Ans=-1;
while(l<=r){
int mid=l+r>>1;
if(check(mid)) Ans=mid,l=mid+1;
else r=mid-1;
}
rep(i,1,n){
int j=i+Ans-1;
if(j>n) break;
if(getgcd(i,j)==getmin(i,j)) ans[++cnt]=i;
}
cout<<cnt<<" "<<Ans-1;el;
rep(i,1,cnt) ptfsp(ans[i]);
}