给定整数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
题意:中文题,不过多叙述题意。
思路:这道题的话,用莫比乌斯反演来做。
易知
最后要用一个类似于分块的公共乘积优化。
AC代码:
#include <stdio.h>
#include <string>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
typedef long long ll;
const int maxx=10000010;
const int mod=10007;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
using namespace std;
int mu[maxx],prime[maxx];
int sum[maxx];
bool vis[maxx];
int cnt;
void get_mu()
{
memset(prime,0,sizeof(prime));
memset(vis,false,sizeof(vis));
memset(sum,0,sizeof(sum));
memset(mu,0,sizeof(mu));
cnt=0;
mu[1]=1;
for(ll i=2; i<=maxx; i++)
{
if(!vis[i])
{
prime[cnt++]=i;
mu[i]=-1;
sum[i]=1;
}
for(ll j=0; j<cnt && i*prime[j]<=maxx; j++)
{
vis[i*prime[j]]=true;
if(i%prime[j])
{
mu[i*prime[j]]=-mu[i];
sum[i*prime[j]]=mu[i]-sum[i];
}
else
{
mu[i*prime[j]]=0;
sum[i*prime[j]]=mu[i];
break;
}
}
}
}
int main()
{
ll n;
get_mu();
while(~scanf("%lld",&n))
{
ll ans=0;
for(ll i=1; i<=n; i++)
{
ans+=sum[i]*(n/i)*(n/i);
}
printf("%lld\n",ans);
}
return 0;
}