判断素数:
普通的就不说了
一种更高效的做法:
结论是:大于等于5的质数一定和6的倍数相邻
令x≥1x≥1,将大于等于55的自然数表示如下: ......6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1............6x−1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1......
可以看到,不在6的倍数两侧,即6x6x两侧的数为6x+2,6x+3,6x+4...6x+2,6x+3,6x+4...由于2(3x+1),3(2x+1),2(3x+2),2(3x+1),3(2x+1),2(3x+2),
所以它们一定不是素数,再除去6x6x本身,显然,素数要出现只可能出现在6x6x的相邻两侧。
所以,基于以上条件,我们假如要判定的数为nn,则nn必定是6x-16x−1或6x+16x+1的形式,对于循环中6i-16i−1,6i6i,6i+16i+1,6i+2,6i+3,6i+46i+2,6i+3,6i+4,其中如果nn能被6i6i,6i+26i+2,6i+46i+4整除,则nn至少得是一个偶数,
但是6x-16x−1或6x+16x+1的形式明显是一个奇数,故不成立;另外,如果nn能被6i+36i+3整除,则n至少能被33整除,
但是6x6x能被33整除,故6x-16x−1或6x+16x+1(即nn)不可能被33整除,故不成立。综上,循环中只需要考虑6i-16i−1和6i+16i+1的情况,
即循环的步长可以定为66,每次判断循环变量kk和k+2k+2的情况即可,代码如下:
bool Is_prime(int n) { if(n==1) return false; if(n==2||n==3) return true; if(n%6!=1&&n%6!=5) return false; for(register int i=5;i*i<=n;i+=6) if(n%i==0||n%(i+2)==0) return false; return true; }
复杂度为:o( sqrt(n)/3 )
1埃拉托斯特尼筛法(最基本方法)
思想:素数的倍数一定不是素数 复杂度:O(nloglogn)
void prime(){ //1表示不是素数,0表示是素数 a[1]=1;//1不是素数 for(int i=2;i*i<=k;i++){//枚举到k开方 if(a[i]==0){ for(int j=i*i;j<=k;j+=i){ //j从i平方开始,每次加i a[j]=1;//这些被穷举到的都不是素数 } } } }