HYSBZ 2818 (GCD)莫比乌斯反演
2016-10-17 00:25
337 查看
E - Gcd
Time Limit:10000MS Memory Limit:262144KB 64bit IO Format:%lld & %llu
Submit Status Practice HYSBZ
2818
Description
给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
Input
一个整数N
Output
如题
Sample Input
Sample Output
Hint
hint
对于样例(2,2),(2,4),(3,3),(4,2)
1<=N<=10^7
对于此题,我们有两种做法。
的对数之和
比如算gcd(x,y)==2的对数,这时y的取值只能是2,4,6,8...2*k
那么gcd(x,2)==2,gcd(x,4)==2,gcd(x,6)==2,gcd(x,8)==2 ... gcd(x,<=n中最大的且是2的倍数的数)==2的对数之和即为gcd(x,y)==2的对数
那么显然gcd(x,y)==2的答案为phi(1)+phi(2)+phi(3)+...phi(n/2)
同理可得gcd(x,y)==3的答案为phi(1)+phi(2)+phi(3)+...phi(n/3)
那么令sum(x)=phi(1)+phi(2)+phi(3)+...phi(x)
那么答案即为∑2*sum(n/prime[i])-1 (考虑(x,y)
(y,x)为两种不同的答案和 (x,x) (x,x) 算同一种答案)
Time Limit:10000MS Memory Limit:262144KB 64bit IO Format:%lld & %llu
Submit Status Practice HYSBZ
2818
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
对于此题,我们有两种做法。
一:欧拉函数
题目可以转化为: 求gcd(x,y)==2 gcd(x,y)==3 gcd(x,y)==5 ... gcd(x,y)==prime的对数之和
比如算gcd(x,y)==2的对数,这时y的取值只能是2,4,6,8...2*k
那么gcd(x,2)==2,gcd(x,4)==2,gcd(x,6)==2,gcd(x,8)==2 ... gcd(x,<=n中最大的且是2的倍数的数)==2的对数之和即为gcd(x,y)==2的对数
那么显然gcd(x,y)==2的答案为phi(1)+phi(2)+phi(3)+...phi(n/2)
同理可得gcd(x,y)==3的答案为phi(1)+phi(2)+phi(3)+...phi(n/3)
那么令sum(x)=phi(1)+phi(2)+phi(3)+...phi(x)
那么答案即为∑2*sum(n/prime[i])-1 (考虑(x,y)
(y,x)为两种不同的答案和 (x,x) (x,x) 算同一种答案)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=1e7+1000; int prime ,phi ,cnt,n;// prime:记录质数,phi记录欧拉函数 int Min_factor ;// i的最小素因子 long long sum ; bool vis ; void Init() { cnt=0; phi[1]=1; int x; for(int i=2;i<N;i++) { if(!vis[i]) { prime[++cnt]=i; phi[i]=i-1; Min_factor[i]=i; } for(int k=1;k<=cnt&&prime[k]*i<N;k++) { x=prime[k]*i; vis[x]=true; Min_factor[x]=prime[k]; if(i%prime[k]==0) { phi[x]=phi[i]*prime[k]; break; } else phi[x]=phi[i]*(prime[k]-1); } } } int main() { Init(); for(int i=1;i<N;i++)sum[i]=sum[i-1]+phi[i]; //sort(prime,prime+cnt); while(scanf("%d",&n)==1) { long long ans=0; for(int i=1;prime[i]<=n;i++) { int k=n/prime[i]; ans+=sum[k]*2-1; } printf("%lld\n",ans); } }
二:莫比乌斯反演(懒得写题解了,直接把草稿放上来啦2333)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; const int maxn=1e7+10; LL prime[maxn],mu[maxn],sum[maxn]; bool vis[maxn]; void getmu(int n) { for(int i=0;i<=n;i++)mu[i]=sum[i]=0; int tot=0; mu[1]=1; for(int i=2;i<=n;i++) { if(!vis[i]) { prime[++tot]=i; mu[i]=-1; sum[i]=1; } for(int j=1;prime[j]*i<=n;j++) { int x=prime[j]*i; vis[x]=1; if(i%prime[j]==0) { mu[x]=0; sum=mu[i]; break; } else { mu[x]=-mu[i]; sum=mu[i]-sum[i]; } } } for(int i=1;i<=n;i++)sum[i]+=sum[i-1]; } int main() { int n; while(scanf("%d",&n)==1) { getmu(n); LL ans=0; for(int i=1;i<=n;i++) { int nxt=n/(n/i); ans+=(sum[nxt]-sum[i-1])*(n/i)*(n/i); i=nxt; } printf("%lld\n",ans); } }
相关文章推荐
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2818(gcd(n,m)为素数的对数
- HYSBZ - 2301 莫比乌斯反演
- bzoj 2818 Gcd 莫比乌斯反演
- BZOJ 2818 Gcd + spoj 4491(莫比乌斯反演 分块)
- 【BZOJ2818】Gcd(莫比乌斯反演,欧拉函数)
- bzoj 2818 Gcd(欧拉函数 | 莫比乌斯反演)
- 【bzoj 2818】Gcd(莫比乌斯反演)
- 【BZOJ2818】Gcd(莫比乌斯反演)
- [BZOJ2818]Gcd(莫比乌斯反演)
- ACM学习历程—HYSBZ 2818 Gcd(欧拉函数 || 莫比乌斯反演)
- BZOJ 2818-Gcd(莫比乌斯反演)