素数筛选法

来源:互联网 发布:学人工智能10本必看书 编辑:程序博客网 时间:2024/06/09 20:48

简单素数筛选法

我们知道,判断一个数是否是素数,只需判断在其算术平方根之前是否有数能 被其整除,因此,简单的素数筛选法便是根据这一思想产生了,即对每一个数的算术平方根开始之前的数都进行判断。

代码如下:
#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;
}
0 0
原创粉丝点击