Bzoj 2818: Gcd 莫比乌斯,分块,欧拉函数,线性筛
2818: Gcd
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3241 Solved: 1437
[Submit][Status][Discuss]
Description
给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
Input
一个整数N
Output
如题
Sample Input
4
Sample Output
4
HINT
hint
对于样例(2,2),(2,4),(3,3),(4,2)
1<=N<=10^7
Source
题解:
莫比乌斯函数或欧拉函数。
莫比乌斯函数详见 Popoqqq的课件 (Orz Po姐)
之后就自己推公式吧。。。
莫比乌斯函数:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define MAXN 10000010 5 int prime[670010],mu[MAXN],qz[MAXN],tot,N; 6 bitset<MAXN> vis; 7 int read() 8 { 9 int s=0,fh=1;char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 12 return s*fh; 13 } 14 void getmu() 15 { 16 int i,j; 17 mu[1]=1; 18 tot=0; 19 for(i=2;i<=N;i++) 20 { 21 if(vis[i]==0) 22 { 23 prime[++tot]=i; 24 mu[i]=-1; 25 } 26 for(j=1;j<=tot&&prime[j]*i<=N;j++) 27 { 28 vis[prime[j]*i]=1; 29 if(i%prime[j]==0) 30 { 31 mu[i*prime[j]]=0; 32 break; 33 } 34 mu[i*prime[j]]=-mu[i]; 35 } 36 } 37 } 38 void Qz() 39 { 40 for(int i=1;i<=N;i++)qz[i]=qz[i-1]+mu[i]; 41 } 42 LL calc(int n) 43 { 44 int d,pos; 45 LL sum=0; 46 for(d=1;d<=n;d=pos+1) 47 { 48 pos=n/(n/d); 49 sum+=(LL)(n/d)*(n/d)*(qz[pos]-qz[d-1]); 50 } 51 return sum; 52 } 53 int main() 54 { 55 int i; 56 LL ans=0; 57 N=read(); 58 getmu(); 59 Qz(); 60 for(i=1;i<=tot&&prime[i]<=N;i++)ans+=calc(N/prime[i]); 61 printf("%lld",ans); 62 fclose(stdin); 63 fclose(stdout); 64 return 0; 65 }
欧拉函数:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 10000010 4 #define LL long long 5 bitset<MAXN> vis; 6 int N,prime[670010],phi[MAXN],tot; 7 LL qz[MAXN]; 8 int read() 9 { 10 int s=0,fh=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 13 return s*fh; 14 } 15 void geteular() 16 { 17 int i,j; 18 phi[1]=1;tot=0; 19 for(i=2;i<=N;i++) 20 { 21 if(vis[i]==0) 22 { 23 prime[++tot]=i; 24 phi[i]=i-1; 25 } 26 for(j=1;j<=tot&&prime[j]*i<=N;j++) 27 { 28 vis[prime[j]*i]=1; 29 if(i%prime[j]==0) 30 { 31 phi[prime[j]*i]=phi[i]*prime[j]; 32 break; 33 } 34 phi[prime[j]*i]=phi[prime[j]]*phi[i]; 35 } 36 } 37 } 38 void Qz() 39 { 40 qz[0]=qz[1]=0; 41 for(int i=2;i<=N;i++)qz[i]=qz[i-1]+phi[i]; 42 } 43 int main() 44 { 45 int i,n; 46 LL ans=0; 47 N=read(); 48 geteular(); 49 Qz(); 50 for(i=1;i<=tot;i++) 51 { 52 n=N/prime[i]; 53 ans+=(qz[n]*2+1); 54 } 55 printf("%lld",ans); 56 fclose(stdin); 57 fclose(stdout); 58 return 0; 59 }