题解:
考虑每个质数
对答案的贡献,
相当于
互质,
为
的数对个数即为
中互质对
的个数。
令
,对于
,
有
个取值使
互质
所以符合条件的互质对
个数为
求一下前缀和就可以了。
关于欧拉函数是什么请自行百科。
那么 怎么快速求?
考虑筛法:
若对于 ,已知所有的 的 ,枚举 的质数 ,可以求得
1、若 与 互质,
2、若不互质,设
似乎过不了 的数据,那么怎么优化呢?
我们发现,很多数被重复计算了,比如
是否能让每个数只被算一次呢?
伪代码:
for i=2->n{
if i是质数{
φ(i)=i-1;
tot=tot+1;
p[tot]=i;
}
for j=1->tot{
p[j]*i标记为合数
计算φ(i*p[j])
if i%p[j]==0 break;//让每个数只被其最小质因子计算到
}
}
#include<bits/stdc++.h>
#define ll long long
#define N 10000005
using namespace std;
int n,p,tot,phi[N],pri[N];
bool b[N];
ll ans,sum[N];
int main()
{
scanf("%d",&n);
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!b[i]){phi[i]=i-1;pri[++tot]=i;}
for(int j=1;j<=tot;j++)
{
int x=pri[j];
if(i*x>n)break;
b[i*x]=1;
if(i%x==0){phi[i*x]=phi[i]*x;break;}
else phi[i*x]=phi[i]*phi[x];
}
}
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+phi[i];
for(int i=1;i<=tot;i++)
ans+=sum[n/pri[i]]*2-1;
printf("%lld",ans);
return 0;
}