我们可以从1开始枚举最大公约数,枚举到n,求出满足gcd(x,y)==i,1<=x,y<=n
,的x,y对数m,i*m累加起来就是答案。
问题是如何求满足gcd(x,y)==i,1<=x,y<=n
,的x,y对数呢?
我们知道满足gcd(x,y)==1,1<=x,y<=n
,的x,y对数是 2 ∗ ∑ 1 n p h i [ i ] − 1 2*\sum_{1}^{n} phi[i] -1 2∗∑1nphi[i]−1,
我们令x=a*i
,y=b*i
,gcd(x,y)==i
就可以表示成gcd(a,b)==1,1<=b*i,a*i<=n
,
所以转化成了gcd为1的情况。答案就是: 2 ∗ ∑ 1 n / i p h i [ i ] − 1 2*\sum_{1}^{n/i} phi[i] -1 2∗∑1n/iphi[i]−1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 1e5+10;
const int mx = 40;
const int mod = 1e9+7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int INF = 1e9+7;
//给定整数n 求满足1<=x,y<=n gcd(x,y)是素数的x y的对数 ,x y可以相同
int vis[maxn];//0表示素数
int book[maxn];//第i个素数
ll phi[maxn];//欧拉函数
ll pre[maxn];
int n;
void phi_primer()
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
book[++book[0]]=i;
phi[i]=i-1;
}
for(int j=1;j<=book[0] && i*book[j]<=n;j++)
{
vis[i*book[j]]=1;
if(i%book[j]==0)
{
phi[i*book[j]]=phi[i]*book[j];
break;
}
else //i book[j]互质
{
phi[i*book[j]]=phi[i]*(book[j]-1);
}
}
}
}
int main()
{
scanf("%d",&n);
phi_primer();
for(int i=1;i<=n;i++) pre[i]=pre[i-1]+phi[i];
ll ans=0;
for(int i=1;i<=n;i++)
{
ans = ans+ i*(pre[n/i]*2-1);
}
printf("%lld",ans);
return 0;
}