欧拉函数~~
第一次写欧拉函数,以前只知道其定义,以为编码按其过程一步一步的实现应该就可以,结果发现不太一样。
超时的想法:首先筛选素数,刚开始是筛选了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 }