判断素数在算法问题中经常遇到,这里编者小白小结了几种求素数的常用方法。
【枚举法】
首先,第一种最常用的方法,便是从1-n逐个判断是否为素数,即逐个判断一个数是否能被2~n-1整除,利用跳出循环时除数与被除数是否相等判断是否为素数。
#include<stdio.h>
int main()
{
int n,m,i;
scanf("%d",&n);
for(m=1;m<=n;m++)
{
for(i=2;i<m;i++)
if(m%i==0)break;
if(i==m)printf("%d\n",m);
}
return 0;
}
基于该种方法,我们可以对其做一些改进:
1.若一个数n不能被2~√n整除,该数即为素数 ;
2.除2之外的偶数均不为素数。
#include<stdio.h>
#include<math.h>
int main()
{
int n,m,i;
scanf("%d",&n);
if(n>=2)printf("%d\n",2);//2做特殊处理
for(m=3;m<=n;m+=2)//偶数除2均不为素数
{
for(i=2;i<=(int)sqrt(m);i++)//优化算法,减少循环次数
if(m%i==0)break;
if(i>(int)sqrt(m))printf("%d\n",m);
}
return 0;
}
【筛法】
接下来第二种方法就是筛法,筛法的基本思路如下:
(1)挖去1:
(2)用下一个未被挖去的数m去除m后面各数,把m的倍数挖掉;
(3)检查m是否小于n的开方的整数部分,如果是,则返回(2)继续执行,否则就结束;
(4)剩下的数就是素数。
附上一张图片帮助大家理解
//筛法求素数:素数的倍数一定不是素数
#include<stdio.h>
#include<math.h>
int main()
{
int n,m,i,x,a[100000];
scanf("%d",&n);
x=sqrt(n);
for(m=1;m<=n;m++)//赋初始值
a[m]=m;
a[1]=0;//挖去1
for(m=2;m<=x;m++)
{
for(i=m+1;i<=n;i++)
if(a[m]!=0&&a[i]!=0)//用下一个未被挖去的数挖去该数的倍数
if(a[i]%a[m]==0)
a[i]=0;
}
for(i=1;i<=n;i++)
if(a[i]!=0)//剩下的数即为素数
printf("%d\n",a[i]);
return 0;
}
【六素数法】
在写最后一种方法之前,先给大家介绍一下孪生素数(间隔为2的相邻素数)
推论:当n>=6时,n-1和n+1为孪生素数,那么n一定为6的倍数。
证明如下:
n-1与n+1是素数,也即n−1和n+1是奇数
∴n是偶数,n是2的倍数。
设n不是3的倍数,即n=3k+1或n=3k+2。
(i)当n=3k+1时,那么n−1=3k,已经与n−1是素数矛盾。
(ii)当n=3k+2时,那么n+1=3(k+1),已经与n+1是素数矛盾。
综上所述,n是3的倍数。
∵n既是2的倍数,又是3的倍数
∴n是6的倍数。
基于此,我们可以把6x(x>=1)附近的数用以下方式表示:
......(6x−1),6x,6x+1,2(3x+1),3(2x+1),2(3x+2),6x+5,6(x+1)......
不在6x两侧的数为:2(3x+1),3(2x+1),2(3x+2),显然它们一定不是素数,所以素数出现在6x的两侧,但在6x两侧的数不一定是素数。(即n>=5时,如果n为素数,则n%6= =1||n%6= =5)
有了以上的理论基础,我们便可以写最后一种方法(六素数法):首先不在6x左右的数2特殊处理,3单独处理,接下来只要判断6x两侧的数是否为素数。因为合数总是可以写成素数的乘积,那么我们直接用n去除以素数就可以达到很好地优化目的。而素数一定是6x两侧的数,且6x两侧的数是大于素数的集合,因此可以用n除以6x两侧的数,即if(n%i==0||n%(i+2)==0)时,不是素数。
//六素数法
#include<stdio.h>
#include<math.h>
int main()
{
int n,i,flag=1;
scanf("%d",&n);
if(n>=2)printf("2\n");//2作特殊处理
for(int i=3;i<=n;i+=2)
{
if(i==3)//3单独处理
printf("3\n");
if(i%6!=1&&i%6!=5)
continue;//不是6x两侧的数不是素数
for(int j=5;j<=(int)sqrt(i);j+=6)//对6x两侧的数进行判断
if(i%j==0||i%(j+2)==0)
{flag=0;break;}
if(flag==0)
{flag=1;continue;}
printf("%d\n",i);
}
return 0;
}