判断素数(判断一个数是不是素数):
最常用解法---sqrt(n)
1 int prime(int n) 2 { 3 if(n<=1) return 0; 4 else if(n==2 || n==3) return 1; 5 else if(n%2==0) return 0; 6 else 7 { 8 int k=sqrt(n); 9 for(int i=2;i<=k;i++) 10 { 11 if(n%i==0) return 0; 12 } 13 return 1; 14 } 15 }
找规律优化版,更快
1 int prime(int n) 2 { 3 if(n==1) return 0; 4 else if(n==2 || n==3) return 1; 5 else if(n%2==0) return 0; 6 else if(n%6!=1 && n%6!=5) return 0; 7 else 8 { 9 int k=sqrt(n); 10 for(int i=5;i<=k;i+=6) 11 { 12 if(n%i==0 || n%(i+2)==0) return 0; 13 } 14 return 1; 15 } 16 }
筛选素数(判断某个范围内所有数是不是素数,或找出所有素数。其实用判断素数循环一遍也行,尤其是有了第二个优化判断素数循环一遍好像比线筛更快!):
埃氏筛选法(又称翻倍法)---n*loglogn
prime数组保存得到的素数;check数组:0表示素数,1合数
1 void Ass(int m) 2 { 3 memset(check,0,sizeof(check)); 4 check[0]=check[1]=1;//这俩非素数 5 6 for(int i=2;i<=m;i++) 7 { 8 if(!check[i]) 9 { 10 prime[++tot]=i; 11 } 12 for(int j=i+i;j<=m;j+=i) 13 { 14 check[j]=1; 15 } 16 } 17 }
但有的数字是多个素数的倍数,也就是说它可能会被重复计算多次,比如说6同时是2与3的倍数,它在计算时就被访问了两次,这样会导致效率低下,所以在下面的算法便优化了这种情况。
欧式筛选法(真正线筛)---n
相当于对埃氏筛的优化,优化了重复计算的筛,使之只被筛一次
1 void Oss(int m) 2 { 3 memset(check,0,sizeof(check)); 4 check[0]=check[1]=1;//这俩非素数 5 6 for(int i=2;i<=m;i++) 7 { 8 if(!check[i]) 9 { 10 prime[++tot]=i; 11 } 12 for(int j=1;j<=tot && i*prime[j]<=m;j++)//优化精华1:只把与素数的积都筛掉 13 { 14 check[i*prime[j]]=1; 15 if(i%prime[j]==0)//优化精华2:保证每个数只被最小素数筛一次最快 16 { 17 break; 18 } 19 } 20 } 21 }
完。