BZOJ 2818 Gcd
2017.09.09
2017.09.09
给定整数N,求1<=x,y<=N且gcd(x,y)为素数的数对(x,y)有多少对.
这道题一看就明白,如果有$(X,Y)$使得$gcd(i,j) = P_i$那么就有$gcd(\frac{i}{P_i},\frac{j}{P_i}) = 1$,所以也就转化成了求小于$\lfloor\frac{n}{P_i}\rfloor$的所有互质数对个数。互质个数……一看就是$phi()$啊!
最终答案$ans=\sum\limits_{i=1}^{tot} \sum\limits_{j=1}^{\lfloor{\frac{n}{P_i}}\rfloor} \varphi(j)$.
#include <cstdio>
#include <algorithm>
using namespace std;
int n,cnt;
long long phi[10000010],prime[10000010],ans;
int use[10000010];
void geteular()
{
phi[1]=1,use[1]=1;
for(int i=2;i<=n;++i)
{
if(!use[i]) prime[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*prime[j]<=n;++j)
{
use[i*prime[j]]=1;
if(!(i%prime[j]))
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
int main()
{
scanf("%d",&n);
geteular();
for(int i=1;i<=n;++i) use[i]=use[i-1]+(use[i]^1);
for(int i=1;i<=n;++i) ans+=phi[i]*(use[n/i]);
ans=(ans<<1)-use[n];
printf("%lld\n",ans);
return 0;
}