UVA - 11426
别人的解释
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=4e6+10;
const int inf=0x3f3f3f3f;
/*线性筛O(n)时间复杂度内筛出maxn内欧拉函数值*/
int m[maxn],phi[maxn],p[maxn],pt;//m[i]是i的最小素因数,p是素数,pt是素数个数
int make()
{
phi[1]=1;
int k;
for(int i=2;i<maxn;i++)
{
if(!m[i])//i是素数
p[pt++]=m[i]=i,phi[i]=i-1;
for(int j=0;j<pt&&(k=p[j]*i)<maxn;j++)
{
m[k]=p[j];
if(m[i]==p[j])//为了保证以后的数不被再筛,要break
{
phi[k]=phi[i]*p[j];
/*这里的phi[k]与phi[i]后面的∏(p[i]-1)/p[i]都一样(m[i]==p[j])只差一个p[j],就可以保证∏(p[i]-1)/p[i]前面也一样了*/
break;
}
else
phi[k]=phi[i]*(p[j]-1);//积性函数性质,f(i*k)=f(i)*f(k)
}
}
}
LL ans[maxn];
void init()//利用因子打表
{
memset(ans,0,sizeof(ans));
for(int i=1;i<maxn;i++)
{
for(int j=i*2;j<maxn;j+=i)
ans[j]+=(LL)(i*phi[j/i]);
}
ans[0]=0;
for(int i=1;i<maxn;i++)//统计前n项和
ans[i]+=ans[i-1];
}
int main()
{
make();
init();
int n;
while(~scanf("%d",&n)&&n)
{
printf("%lld\n",ans[n]);
}
}