Description
给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
注意,若x!=y,则(x,y)与(y,x)都要计算在内。
1<=N<=10^7
Analysis
设
gcd(px,py)=p,p
为素数。
满足上式的
x,y
必然互质。
因此
预处理 φ 的前缀和,直接 O(n) 扫过。
但是,身为蒟蒻的我,太弱,竟然忘了 φ 的线筛预处理,赶紧恶补了一下。
φ的预处理
因为线筛只可能出现
gcd(x,y)=1
或
y|x
的情况,所以我们只用对这两种情况讨论。
首先,因为
φ
是积性函数,所以若
gcd(x,y)=1
,则
φ(x∗y)=φ(x)∗φ(y)
。
而若
y|x
,则
φ(x∗y)=φ(x)∗y
,证明如下:
正难则反,首先有一个神奇的性质。
若
n,m
不互质,设其
gcd
为
b
,则有
n+m=(k1+k2)b
,亦不与
n
或
[1,x]
中与
x
不互质的数个数为
所以
[x+1,x+x]
中与
x+x
不互质的数的个数亦为
x−φ(x)
个。
⋯⋯
[1,x∗y]
中与
x
不互质的数的个数为
即与
x
互质的数的个数就是
Code
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int N=int(1e7);
int n,pri[N];
ll ans,phi[N];
bool bz[N];
void pre(int n)
{
phi[1]=1;
fo(i,2,n)
{
if(!bz[i]) bz[i]=1,pri[++pri[0]]=i,phi[i]=i-1;
fo(j,1,pri[0])
{
int t=i*pri[j];
if(t>n) break;
bz[t]=1;
if(i%pri[j]==0)
{
phi[t]=phi[i]*pri[j];
break;
}
phi[t]=phi[i]*phi[pri[j]];
}
}
fo(i,3,n) phi[i]+=phi[i-1];
}
int main()
{
scanf("%d",&n);
pre(n);
fo(i,1,pri[0])
{
if(n/pri[i]<2) break;
ans+=phi[n/pri[i]]*2;
}
printf("%lld",ans+pri[0]);
return 0;
}