HDU 5726 - GCD

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:\n",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\n",ans,m[ans]);
65         }
66     }
67 } 

 

posted @ 2017-05-04 23:21  Dilthey  阅读(233)  评论(0编辑  收藏  举报