题目大意:给定整数 (N),求(1le x,yle N) 且 (gcd(x,y)) 为素数的数对 ((x,y)) 有多少对。
题解:
[sum_{p in ext { prime }} sum_{i=1}^{n} sum_{j=1}^{n}[operatorname{gcd}(i, j)=p]
]
[sum_{p in ext { prime }} sum_{i=1}^{leftlfloorfrac{n}{p}
ight
floor} sum_{j=1}^{leftlfloorfrac{n}{p}
ight
floor}[operatorname{gcd}(i, j)=1]
]
[sum_{p in ext { prime }}left(sum_{i=1}^{leftlfloorfrac{n}{p}
ight
floor}left(2 sum_{j=1}^{i}[operatorname{gcd}(i, j)=1]
ight)-1
ight)
]
[sum_{p in ext { prime }}left(2 sum_{i=1}^{leftlfloorfrac{n}{p}
ight
floor} varphi(i)-1
ight)
]
因此,利用线性筛求出欧拉函数的前缀和,直接枚举素数计算答案贡献即可。
代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+10;
int n,prime[maxn],tot;
ll phi[maxn],sum[maxn];
bool vis[maxn];
void sieve(){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i])prime[++tot]=i,phi[i]=i-1;
for(int j=1;i*prime[j]<=n;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}else{
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+phi[i];
}
int main(){
scanf("%d",&n);
sieve();
ll ans=0;
for(int i=1;i<=tot;i++)ans+=(2*sum[n/prime[i]]-1);
printf("%lld
",ans);
return 0;
}