题目链接:http://codeforces.com/contest/475/problem/D
是昨天晚上的CF题目,题意是给定你n个数,问你所有子区间内的最小公约数是x的个数是多少
问的康神,了解了ST表。
其实我也没太明白,看了看博文觉得还是不错的:http://hplonline20100103.blog.163.com/blog/static/1361364342010040044244/
然后就是logn去扫了
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 int ST[250100][19]; 6 7 int getGCD(int l,int r){ 8 int u = 31-__builtin_clz(r-l+1); 9 return __gcd(ST[l][u],ST[r+1-(1<<u)][u]); 10 } 11 12 map<int,LL> mp; 13 14 int main(){ 15 int n; 16 scanf("%d",&n); 17 for(int i=0;i<n;i++) scanf("%d",&ST[i][0]); 18 for(int j=0;(1<<j)<=n;j++) for(int i=0;i<n;i++) 19 ST[i][j+1]=__gcd(ST[i][j],ST[i+(1<<j)][j]); 20 for(int i=0;i<n;i++){ 21 int ed = i; 22 while( ed<n ){ 23 int g = getGCD(i,ed); 24 int l=ed,r=n-1,ge=-1; 25 while( l<=r ){ 26 if( r-l<=1 ){ 27 if(getGCD(i,r)==g){ ge=r;break; } 28 if( getGCD(i,l)==g )ge=l; 29 break; 30 } 31 int m = l+r>>1; 32 if( getGCD(i,m)==g ) l = m; 33 else r = m; 34 } 35 mp[g]+=ge-ed+1; 36 ed = ge+1; 37 } 38 } 39 int Q; 40 scanf("%d",&Q); 41 while(Q--){ 42 int x; 43 scanf("%d",&x); 44 printf("%I64d\n",mp[x]); 45 } 46 return 0; 47 }
浙公网安备 33010602011771号