欧拉函数~~

第一次写欧拉函数,以前只知道其定义,以为编码按其过程一步一步的实现应该就可以,结果发现不太一样。

超时的想法:首先筛选素数,刚开始是筛选了N以内的所有素数,然后对于每个数,从小到大枚举素数,

for(;;)//枚举素数

if(n%prime[i]==0)

{

   phj[n]=phj[n]-phj[n]/prime[i];

   while(n%prime[i]==0)

   {

        n/=prime[i];

    }

}

超时了之后,发现素数其实没必要枚举到N,只用枚举到sqrt(N)

因为对于每一个数n,for()循环之后,如果n不为1,那n肯定是一个大于sqrt(N)的素数。

但是这样之后还是超时了。。

之后看了百科上面的算法,他是对每一个素数,枚举他的倍数,这样每一步都是有效的,效率就提高了。

View Code
 1 # include<stdio.h>
 2 # include<string.h>
 3 # include<stdlib.h>
 4 # define N 3000005
 5 bool vis[N];
 6 int phj[N];
 7 //__int64 sum[N];
 8 int main()
 9 {
10     int i,j,a,b;
11     __int64 ans;
12     memset(vis,0,sizeof(vis));
13     for(i=2;i*i<3000000;i++)
14     {
15         if(vis[i]) continue;
16         for(j=i+i;j<3000000;j+=i)
17             vis[j]=1;
18     }
19     for(i=3;i<3000000;i++)
20         phj[i]=i;
21     for(i=2;i<3000000;i++)
22     {
23         if(vis[i]==0)
24         {
25             for(j=i;j<3000000;j+=i)
26                 phj[j]=phj[j]-phj[j]/i;
27         }
28     }
29     /*sum[2]=0;
30     for(i=3;i<=3000000;i++)
31         sum[i]=sum[i-1]+phj[i];*/
32     while(scanf("%d%d",&a,&b)!=EOF)
33     {
34         ans=0;
35         for(i=a;i<=b;i++)
36             ans+=phj[i];
37         printf("%I64d\n",ans);
38         //printf("%I64d\n",sum[b]-sum[a-1]);
39     }
40     return 0;
41 }

 

 

 

posted on 2012-09-20 16:20  奋斗青春  阅读(413)  评论(0编辑  收藏  举报