KunKun的征途

明天的明天,你还会送我水晶之恋吗?

导航

[CF 475D] CGCDSSQ (RMQ)

Posted on 2014-10-06 22:13  西域小车  阅读(340)  评论(0)    收藏  举报

题目链接: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 }
View Code