poj 2478(快速求解欧拉函数优化版。。。)

之前一直在用

void get_eular() {
    memset(eul,0,sizeof(eul));
    eul[1]=1;
    for(int i=2;i<maxlen;i++)
        if(!eul[i])
            for(int j=i;j<maxlen;j+=i){
                if(!eul[j]) eul[j]=j;
                eul[j]=eul[j]/i*(i-1);
            }
    eul[1]=0;eul[2]=1;
    for(int i=3;i<maxlen;i++){
        eul[i]+=eul[i-1];
    }
}
来求前n项的欧拉函数值。。。后来发现了一个比较好的优化。。。。。请看这里的一个讲解  http://www.cnblogs.com/suno/archive/2008/02/04/1064368.html 

然后按照优化方案来写程序。。。进入了100ms以内了。。。。嗨皮。。


#include <iostream>
#include <cstdio>
#include<cstring>
using namespace std;
const int maxlen=1000010;
long long eul[maxlen];
int pri[maxlen],f[maxlen],isprim[maxlen],p=0;
inline void get_prim(){
    memset(isprim,1,sizeof(isprim));
    for(int i=2;i<maxlen;i++){
        if(isprim[i]) pri[p++]=i;
        for(int j=0;j<p && i*pri[j]<maxlen;j++){
            int k=pri[j]*i;
            isprim[k]=0,f[k]=pri[j]; // 得到k的最小素因子
            if(i%pri[j]==0) break;
        }
    }
}
inline void get_eul(){
    for(int i=2;i<maxlen;i++)
        if(isprim[i]) eul[i]=i-1;
        else{
            int k=i/f[i];
            if(k%f[i]==0) eul[i]=eul[k]*f[i];
            else eul[i]=eul[k]*(f[i]-1);
        }
    for(int i=3;i<maxlen;i++)
        eul[i]+=eul[i-1];
}
int main(int argc, char** argv) {
    int m;
    get_prim();
    get_eul();
    while(scanf("%d",&m) && m)
        printf("%lld\n",eul[m]);
    return 0;
}


你可能感兴趣的:(poj 2478(快速求解欧拉函数优化版。。。))