给n个数,q次询问,每次问区间[l,r]的GCD以及整个区间内有多少个gcd为此的区间。
求区间gcd很好求,而有多少个这样的gcd,可以预处理出区间所有的gcd,因为一个n个数的区间最多有logn种gcd,所有暴力枚举即可。
#include <bits/stdc++.h> #define pb push_back #define mp make_pair #define fi first #define se second #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define up rt,rt<<1,rt<<1|1 #define mem(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) using namespace std; typedef long long ll; typedef double db; const int M = 1e5+7; const double pi = acos(-1); const int inf = 2147483647; const int mod = 1e9+7; int _,n,q,a[M],cas=1; map<int,ll> mp1,mp2,mp3; //mp1存前面的所有可以和下面一个数连续的区间的gcd,mp2存每加入一个数新的gcd,mp3存所有的gcd void init(){ mp1.clear();mp2.clear();mp3.clear(); for(int i=1;i<=n;i++){ for(map<int,ll>::iterator it=mp2.begin();it!=mp2.end();it++){ mp1[it->fi]=it->se; } mp2.clear(); for(map<int,ll>::iterator it=mp1.begin();it!=mp1.end();it++){ mp2[__gcd(it->fi,a[i])]+=it->se;mp3[__gcd(it->fi,a[i])]+=it->se; } mp2[a[i]]++;mp3[a[i]]++; mp1.clear(); } } int g[M<<2]; void pushup(int rt,int l,int r){ g[rt]=__gcd(g[l],g[r]); } void build(int l,int r,int rt){ if(l==r){ g[rt]=a[l]; return ; } int mid=(l+r)>>1; build(lson); build(rson); pushup(up); } int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return g[rt]; } int mid=(l+r)>>1; if(R<=mid) return query(L,R,lson); else if(L>mid) return query(L,R,rson); else return __gcd(query(L,R,lson),query(L,R,rson)); } int main(){ #ifdef LMissher freopen("1.in","r",stdin); freopen("1.out","w",stdout); #endif scanf("%d",&_); while(_--){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); init(); build(1,n,1); scanf("%d",&q); printf("Case #%d:\n",cas++); while(q--){ int l,r; scanf("%d%d",&l,&r); int ans=query(l,r,1,n,1); printf("%d %lld\n",ans,mp3[ans]); } } return 0; }