我们筛出N以内所有的素数,同时求出从1-N所有的欧拉函数值,最后枚举素数累加答案即可。
#include "iostream"
using namespace std;
typedef long long ll;
const int N=10000005;
int n,tmp;
int eular[N],prime[N];
ll sum,esum[N];
void Eular_All(){ ll i,j;
//筛选从1-n的Eular函数
//若 n=ij 且i与j互素 eular(n)= eular(i)*eular(j);
//若 n为素数 eular(n)=n-1
//若 n为素数平方数 eular(n)= n-sqrt(n)
eular[1]=1;
for (i=2;i<=n;i++)
{ // 每次可以更新到所有i^2后的答案
if (eular[i]==0) // 还没有fill过
{ prime[++tmp]=i;
eular[i]=i-1;
if(i*i<=n)
eular[i*i]=i*i-i;
}
for (j=1;j<tmp&&i*prime[j]<=n;j++) //计算i*prime[j]的答案
{
if(i%prime[j])//互素
eular[i*prime[j]]=eular[i]*eular[prime[j]];
else //i恰为prime[j]的倍数
eular[i*prime[j]]=eular[i]*prime[j];
}
}
for (i=1;i<=n;i++)
esum[i]=esum[i-1]+eular[i];
}
int main(){
cin>>n; int i;
Eular_All();
for (i=1;i<=tmp;i++)
sum += esum[n/prime[i]]*2-1;
cout<< sum <<endl;
return 0;
}