简单素数筛选法
我们知道,判断一个数是否是素数,只需判断在其算术平方根之前是否有数能 被其整除,因此,简单的素数筛选法便是根据这一思想产生了,即对每一个数的算术平方根开始之前的数都进行判断。
代码如下:#include <stdio.h>
#include <math.h>
#define MAX 100
int prime[MAX+1];
int main()
{
int j,k=0;
for(int i=2;i<=MAX;i++)
{
for(j=2;j<=sqrt(i);j++)
if(i%j==0 )
break;
if(j>sqrt(i))
prime[k++]=i;
}
for(int i=0;i<k;i++)
printf("%d ",prime[i]);
printf("\n");
return 0;
}
快速素数筛选法
然而简单的素数筛选法的耗时比较长,尤其是求的素数范围比较大的时候,在oj做题时,基本上有简单素数筛选法的代码,都超时了。因此我就去学习一种快速筛选法。这种筛选法主要思想就是假如一个数是素数,那么它的2倍,3倍....n倍必定是合数。而且素数除2之外全部都是奇数,我们建立一个数组,令数组奇数下标等于0,数组偶数下标等于1,同时,在确定一个数是素数的时候,将其倍数下标的数也赋值为1,这样一来,只有数组下标等于0的数才是奇数,数组下标等于1的,不用考虑,因此省去了不少时间
代码如下:#include <stdio.h>
#define MAX 100
int a[MAX+1];
int prime[MAX+1];
int main()
{
int k=0;
prime[k]=2;
for(int i=3;i<=MAX;i++)
{
if(i%2==0)
a[i]=1;
else
a[i]=0;
}
for(int i=3;i<=MAX;i+=2)
{
if(a[i]==0)
prime[++k]=i;
for(int j=i*2;j<=MAX;j+=i)
a[j]=1;
}
for(int i=0;i<=k;i++)
printf("%d ",prime[i]);
printf("\n");
return 0;
}
代码优化
快速筛选法虽然比较好,但是其仍然有一些计算是重复了,比如偶数下标的数不需要计算;但是我们仍然给其赋值;而且有的数甚至重复赋值,比如在计算3的倍数的时候,将15赋值为1,在计算5的倍数的时候,又将15赋值为1,这样就花费了不少时间。因此我们可以将下标为偶数的不予计算,只计算奇数下标的即可。另外,我们发现,当只计算奇数的时候,a数组中下标为0对应的则是3,下标为1时 对应的是5下标为2时,对应的是7......,即i*2+3的关系,另外,因为我们不对偶数进行计算,因此当筛选的倍数只能是3倍,5倍....
代码如下:
#include <stdio.h>#include <math.h>
#define MAX 100
int a[MAX+1];
int prime[MAX+1];
int main()
{
int k=0;
prime[k]=2;
for(int i=0;i*2+3<=MAX;i++)
a[i]=0;
for(int i=0;i*2+3<=MAX;i++)
{
if(a[i]==0)
prime[++k]=i*2+3;
for(int j=3*(i*2+3);j<=MAX;j+=2*(i*2+3))
a[(j-3)/2]=1;
}
for(int i=0;i<=k;i++)
printf("%d ",prime[i]);
printf("\n");
return 0;
}