素数相关问题

判断素数(判断一个数是不是素数):
最常用解法---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 }

 

完。

posted @ 2018-10-12 10:13  RedBlack  阅读(160)  评论(0编辑  收藏  举报