GCD (hdu 5726)

GCD

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1497    Accepted Submission(s): 483


Problem Description
Give you a sequence of N(N100,000) integers : a1,...,an(0<ai1000,000,000). There are Q(Q100,000) queries. For each query l,r you have to calculate gcd(al,,al+1,...,ar) and count the number of pairs(l,r)(1l<rN)such that gcd(al,al+1,...,ar) equal gcd(al,al+1,...,ar).
 

 

Input
The first line of input contains a number T, which stands for the number of test cases you need to solve.

The first line of each case contains a number N, denoting the number of integers.

The second line contains N integers, a1,...,an(0<ai1000,000,000).

The third line contains a number Q, denoting the number of queries.

For the next Q lines, i-th line contains two number , stand for the li,ri, stand for the i-th queries.
 

 

Output
For each case, you need to output “Case #:t” at the beginning.(with quotes, t means the number of the test case, begin from 1).

For each query, you need to output the two numbers in a line. The first number stands for gcd(al,al+1,...,ar) and the second number stands for the number of pairs(l,r) such that gcd(al,al+1,...,ar) equal gcd(al,al+1,...,ar).
 

 

Sample Input
1 5 1 2 4 6 7 4 1 5 2 4 3 4 4 4
 

 

Sample Output
Case #1: 1 8 2 4 2 4 6 1
 

 

Author
HIT
 

 

Source
思路:RMQ+二分
一开始我用的线段树去维护各个区间的gcd但是超时,并且我没有优化。
暴力统计的各个区间的gcd;
后来发现gcd的性质,也就是求数的gcd,这些数的个数越多那么gcd越小,所以从左到右,以某个端点开始的gcd的大小随着区间增大而减小,那么二分统计以某个点为端点的gcd
最多每个端点二分30次。
然后还是超时。
然后改用RMQ基于稀疏表的,查询O(n);
复杂度(n*log(n));
 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<string.h>
 5 #include<stdlib.h>
 6 #include<queue>
 7 #include<map>
 8 #include<math.h>
 9 using namespace std;
10 typedef long long LL;
11 int RMQ[20][100005];
12 int ans[100005];
13 map<int,LL>my;
14 int gcd(int n,int m)
15 {
16         if(m==0)
17                 return n;
18         else  if(n%m==0)
19         {
20                 return m;
21         }
22         else return gcd(m,n%m);
23 }
24 int main(void)
25 {
26         int i,j,k;
27         int n,m;
28         scanf("%d",&k);
29         int ca=0;
30         while(k--)
31         {
32                 my.clear();
33                 scanf("%d",&n);
34                 for(i=1; i<=n; i++)
35                 {
36                         scanf("%d",&ans[i]);
37                 }
38                 for(i=1; i<=n; i++)
39                 {
40                         RMQ[0][i]=ans[i];
41                 }
42                 scanf("%d",&m);
43                 for(i=1; i<20; i++)
44                 {
45                         for(j=1; j<=n; j++)
46                         {
47                                 if(j+(1<<i)-1<=n)
48                                 {
49                                         RMQ[i][j]=gcd(RMQ[i-1][j],RMQ[i-1][j+(1<<(i-1))]);
50                                 }
51                         }
52                 }
53                 for(i=1; i<=n; i++)
54                 {
55                         for(j=i; j<=n;)
56                         {
57                                 int t=log2(j-i+1);
58                                 int ac=gcd(RMQ[t][i],RMQ[t][j-(1<<t)+1]);
59                                 int l=j;
60                                 int r=n;
61                                 int id=0;
62                                 while(l<=r)
63                                 {
64                                         int mid=(l+r)/2;
65                                         int c=log2(mid-i+1);
66                                         int ak=gcd(RMQ[c][i],RMQ[c][mid-(1<<c)+1]);
67                                         if(ak>=ac)
68                                         {
69                                                 id=mid;
70                                                 l=mid+1;
71                                         }
72                                         else r=mid-1;
73                                 }
74                                 my[ac]+=id-j+1;
75                                 j=id+1;
76                         }
77                 }
78                 printf("Case #%d:\n",++ca);
79                 while(m--)
80                 {
81                         int x,y;
82                         scanf("%d %d",&x,&y);
83                         if(x>y)
84                         {
85                             swap(x,y);
86                         }
87                         int ct=log2(y-x+1);
88                         int acc=gcd(RMQ[ct][x],RMQ[ct][y-(1<<ct)+1]);
89                         printf("%d %lld\n",acc,my[acc]);
90                 }
91         }
92         return 0;
93 }

 

posted @ 2016-07-20 22:07  sCjTyC  阅读(577)  评论(0编辑  收藏  举报