RMQ应用题。
引用别人的解题思路:
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<map> 5 #define MAXN 100000+5 6 using namespace std; 7 map<int,long long> m; 8 int n,a[MAXN],q; 9 int dp[MAXN][17]; 10 int gcd(int a,int b){return b==0?a:gcd(b,a%b);} 11 void RMQ_init() 12 { 13 for(int i=1;i<=n;i++) dp[i][0]=a[i]; 14 double j_max=(log(n)/log(2.0)); 15 for(int j=1;j<=j_max;j++) 16 { 17 for(int i=1;i<=n;i++) 18 if(i+(1 << j)-1 <= n) dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); 19 } 20 } 21 int query(int l,int r) 22 { 23 int k=log(r-l+1)/log(2.0); 24 return gcd(dp[l][k],dp[r-(1<<k)+1][k]); 25 } 26 void pretreat()//这个预处理是需要好好理解的地方 27 { 28 m.clear(); 29 for(int l=1;l<=n;l++) 30 { 31 int r=l; 32 while(r <= n) 33 { 34 int d=query(l,r); 35 int st=r,ed=n,mid; 36 while(ed-st>1) 37 { 38 mid=(st+ed)>>1; 39 if(query(l,mid) == d) st=mid; 40 else ed=mid; 41 } 42 m[d]+=st-r+1; 43 r=st+1; 44 } 45 } 46 } 47 int main() 48 { 49 int t; 50 scanf("%d",&t); 51 for(int kase=1;kase<=t;kase++) 52 { 53 scanf("%d",&n); 54 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 55 RMQ_init(); 56 pretreat(); 57 scanf("%d",&q); 58 int l,r; 59 printf("Case #%d: ",kase); 60 for(int i=1;i<=q;i++) 61 { 62 scanf("%d%d",&l,&r); 63 int ans=query(l,r); 64 printf("%d %I64d ",ans,m[ans]); 65 } 66 } 67 }