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 }