题目大意:给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
我会暴力!直接枚举质数,然后莫比乌斯反演求互质数对,这样做的理论复杂度是O(质数个数*根号(N/质数)),慢是慢了点,不过BZOJ开O2还是可以卡过的~~
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=10000000+10;
int hm[maxn],tot,mu[maxn],check[maxn],n,m;
void pre()
{
check[1]=1;mu[1]=1;
for(int i=2;i<=maxn-10;i++)
{
if(!check[i])
{
hm[++tot]=i;
mu[i]=-1;
}
for(int j=1;j<=tot&&(long long)i*hm[j]<=maxn-10;j++)
{
check[i*hm[j]]=1;
if(i%hm[j]==0)
{
mu[i*hm[j]]=0;
break;
}
mu[i*hm[j]]=-mu[i];
}
}
for(int i=1;i<=maxn-10;i++)
mu[i]+=mu[i-1];
}
long long solve(int n,int m)
{
long long res=0;int d=1,l=min(n,m);
while(d<=l)
{
int v1=n/(n/d),v2=m/(m/d);
v1=min(v1,v2);
res+=(long long)(mu[v1]-mu[d-1])*(n/v1)*(m/v1);
d=v1+1;
}
return res;
}
int main()
{
//freopen("2818.in","r",stdin);
//freopen("2818.out","w",stdout);
pre();scanf("%d",&n);long long ans=0;m=n;
for(int i=1;i<=tot&&hm[i]<=n;i++)
ans+=solve(n/hm[i],m/hm[i]);
printf("%lld\n",ans);
return 0;
}