题目描述
给定整数N,求1<=x,y<=N(N<=10^7)且Gcd(x,y)为素数的
数对(x,y)有多少对.
输入
一个整数N
输出
如题
样例输入
4
样例输出
4
解题思路:
这个题目出来可以用欧拉函数来解答之外,点击此处 这是欧拉函数解这道题的思路
那么我们还可以用莫比乌斯反演来做,首先介绍一下莫比乌斯反演的公式:
F(n)=∑d|nf(d) ⇒f(n)=∑d|nF(nd)miu(d)−−−(1)
其实还可以这么写:
F(n)=∑n|df(d) ⇒f(n)=∑n|dmiu(dn)F(d)−−−(2)
在这道题里面就可以这么设了,那么我们现在可以给两个f函数赋值了:
f(d):是满足GCD(x,y)==d的(1<=x,y<=n)的对数
F(d):是满足d|GCD(x,y)的函数(1<=x,y<=n)的对数
那么我们可以写出
F(d)=nd∗nd−−−(3)
所以根据式子(2)和(3)可以知道
f(n)=∑n|dmiu(dn)nd∗nd
又因为 GCD(x,y) 是素数,那么我们可以枚举区间[1,n]的每个素数(素因子分解可以实现)
ans=∑pn(∑dnmiu(d)np∗d∗np∗d)(在这里p是素数)
然后再YY一下就可以搞定了。。。
这里的miu就是代码里面的mu数组
#include<stdio.h>
#include<string.h>
#include<math.h>
#include <queue>
#include <iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int INF=0x7fffffff;
const int N=1000000+1;
int prime[N],mu[N],vis[N],phi[N];
/*
因为 GCD(x,y) 是素数,那么我们可以枚举区间[1,n]的每个素数(素因子分解可以实现)
ans=n∑p(n∑d miu(d)(n/(p*d))*(n/(p*d)))(在这里p是素数)
*/
void Moblus()
{ //O(log(n))
int i,j;
memset(vis,0,sizeof(vis));
mu[1]=1;
int cnt=0;
for (i=2;i<N;i++)
{
if (!vis[i])
{
prime[cnt++]=i;
mu[i]=-1;
phi[i]=1;
}
for (j=0;j<cnt&&i*prime[j]<N;j++)
{
vis[i*prime[j]]=1;
if (i%prime[j])
{
mu[i*prime[j]]=-mu[i];
phi[i*prime[j]]=mu[i]-phi[i];
}
else{
mu[i*prime[j]]=0;
phi[i*prime[j]]=mu[i]; //mu[i]=prime[j]*phi[i]
break;
}
}
}
}
int sum[N];
void getSum()
{
int i;
sum[0]=0;
for (i=1;i<N;i++)
sum[i]=sum[i-1]+phi[i];
}
int main()
{
int i,last;
Moblus();
getSum();
ll n,ans=0;
scanf("%lld",&n);
for (i=1,last=0;i<=n;i=last+1)
{
last=n/(n/i);
ans+=(n/i)*(n/i)*(sum[last]-sum[i-1]);
}
printf("%lld\n",ans);
return 0;
}