hdu5726-GCD-ST表+二分
先用st表处理出所有l-r的GCD值,然后二分求得这些值一共出现了多少次。
1 #include<bits/stdc++.h> 2 3 #define inf 0x3f3f3f3f 4 5 const int maxn=100000; 6 7 using namespace std; 8 9 typedef pair<int,int> P; 10 11 int l,r; 12 13 int icase; 14 15 int t,n,q; 16 17 int a[maxn+1]; 18 19 int dp[maxn+1][20]; 20 21 map<int,long long> m; 22 23 int gcd(int a,int b){ 24 return b==0?a:gcd(b,a%b); 25 } 26 27 void RMQ(){ 28 for(int i=1;i<=n;i++){ 29 dp[i][0]=a[i]; 30 } 31 for(int j=1;j<20;j++){ 32 for(int i=1;i<=n;i++){ 33 if(i+((1<<(j-1))-1)<=n) 34 dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); 35 //printf("%d\n",dp[i][j]); 36 } 37 } 38 } 39 40 int query(int l,int r){ 41 int k=(int)log2(double(r-l+1)); 42 return gcd(dp[l][k],dp[r-(1<<k)+1][k]); 43 } 44 45 void Cal(){ 46 for(int i=1;i<=n;i++){ 47 int GCD=a[i],tail=i; 48 while(tail<=n){ 49 int lb=tail,ub=n,mid=(lb+ub)>>1; 50 while(ub-lb>1){ 51 mid=(lb+ub)>>1; 52 if(query(i,mid)==GCD) lb=mid; 53 else ub=mid; 54 } 55 if(query(i,ub)==GCD){ 56 m[GCD]+=(ub-tail+1); 57 tail=ub+1; 58 GCD=query(i,tail); 59 } else if(query(i,mid)==GCD){ 60 m[GCD]+=(mid-tail+1); 61 tail=mid+1; 62 GCD=query(i,tail); 63 } 64 else{ 65 m[GCD]+=(lb-tail+1); 66 tail=lb+1; 67 GCD=query(i,tail); 68 } 69 } 70 } 71 } 72 73 void solve(){ 74 scanf("%d",&n); 75 for(int i=1;i<=n;i++){ 76 scanf("%d",&a[i]); 77 } 78 RMQ(); 79 Cal(); 80 scanf("%d",&q); 81 printf("Case #%d:\n",++icase); 82 while(q--){ 83 scanf("%d%d",&l,&r); 84 int res=query(l,r); 85 printf("%d %I64d\n",res,m[res]); 86 } 87 } 88 89 void init(){ 90 m.clear(); 91 memset(dp,0,sizeof(dp)); 92 } 93 94 int main() 95 { 96 scanf("%d",&t); 97 while(t--){ 98 init(); 99 solve(); 100 } 101 return 0; 102 }