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]); } }