HYSBZ 2818 gcd

 1 /**
 2 大意: 给定整数N,1<= x,y <= N 求解有多少gcd(x,y) 为素数  n=10^7
 3 思路:    首先考虑到n 如此之大,用的快速求欧拉函数。
 4    先默认 y〉x
 5 分析:   gcd(x,y) =2,   gcd(x,y) = 3, gcd(x,y) = 5, gcd(x,y) = 7。。。。
 6 即 gcd(x,y/2) =1,   gcd(x, y/3) =1, gcd(x, y/5) =1,  gcd(x,y/7) = 1 。。。。
 7 以gcd(x,y) = 2  为例  -----> gcd(x,y/2) = 1;
 8 就是求比y/2小的所有与y/2 互质数的个数。。。y取值为2,4,6,8,10.。。。
 9 所以siga(gcd(x,2)=2 + gcd(x,4) =2 + gcd( x,6) =2 + 。。。)= 
10 ----->siga(gcd(x,1)=1 + gcd(x,2) =1 + gcd( x,3) =1 + 。+ gcd(x,n/2)=1)
11 其他的同理。。。
12 所以先预处理 小于n 的所有互质数的个数 s[i] = s[i-1]+phi[i];
13 使用时   
14 if(n>=prime[i]){
15             ans += 2*s[n/prime[i]]-1;  (也有可能x 〉y)
16   }
17 **/
18 
19 #include <iostream>
20 #include <cstring>
21 #include <algorithm>
22 using namespace std;
23 
24 #define Max 10000000
25 
26 long long  s[Max+5],f[Max+5],phi[Max+5];
27 int prime[Max/10];
28 bool flag[Max+5];
29 int num;
30 void init()
31 {
32     int i,j;
33     num=0;
34     memset(flag,1,sizeof(flag));
35     phi[1]=1;
36     for(i=2;i<=Max;i++){//欧拉筛选
37         if(flag[i])
38         {
39             prime[num++]=i;
40             phi[i]=i-1;
41         }
42         for(j=0;j<num && prime[j]*i<=Max;j++)
43         {
44             flag[i*prime[j]]=false;
45             if(i%prime[j]==0)
46             {
47                 phi[i*prime[j]]=phi[i]*prime[j];
48                 break;
49             }
50             else phi[i*prime[j]]=phi[i]*(prime[j]-1);
51         }
52     }
53     s[0] =0;
54     for(int i=1;i<Max;i++)
55         s[i] = s[i-1]+phi[i];
56 }
57 
58 
59 int main(){
60     init();
61     long long n;
62     while(cin>>n){
63         long long ans =0;
64         for(int i=0;i<num;i++)
65         if(n>=prime[i]){
66             ans += 2*s[n/prime[i]]-1;
67         }
68         cout<<ans<<endl;
69     }
70 }

 

posted @ 2014-05-12 19:34  夜晓楼  阅读(776)  评论(0编辑  收藏  举报