求小于N的所有素数

 

  1. 解法1:检查每一个数K,在2~sqrt(K)区间内是否含有它的因子。
  2. 解法2:我们可以按照从1到N的顺序来验证一个数是否为质数,这样当我们验证K的时候,所有小于K的质数都已经求得。那么我们没必要验证2~sqrt(K)区间内的有没有K的因子,我们只需要验证这个区间内的所有质数中有没有K的因子。
  3. 解法3:筛选法,先假设所有数都是质数,然后从2开始筛掉所有2的倍数,然后从没被筛掉的第一个数开始,继续筛选。每一个数被筛选了X次,X为它的质因子数目-2。
  4. 解法4:筛选法,在上述筛选法中每一个数被筛选了X次。例如6,它被2和3各筛选了1次。如何避免这种重复筛选呢?我们可以把一个合数分解为a×p,p为a的最小质因子,这样对于任何一个合数,就都有了一个唯一二元组(a,p)与之对应,我们每次都通过一个不同的(a,p)来覆盖,就可以保证没有重复的覆盖。也就是说循环的次数为小于N的合数的个数。

  

算法的效率4>3>2>1

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;

//求素数表集中方法的比较

#define TABLE_LEN             20000000
#define PRIME_UP_BOUND        130000000

bool bPrime[PRIME_UP_BOUND];
int PrimeTable[TABLE_LEN];
int ptc;
int LC;        //循环计数器

void MakeTable1(int n)
{
    int i,j,b;
    ptc = 0;
    PrimeTable[ptc++] = 2;
    for(int i = 3; i < n; i++)
    {
        b = 1;
        for(int j = 2; b && j * j <= i; j++)
        {
            LC++;
            b = i % j;
        }
        b ? PrimeTable[ptc++] = i : 0;
    }
}

void MakeTable2(int n)
{
    int i,j,b;
    ptc = 0;
    PrimeTable[ptc++] = 2;
    for(int i = 3; i < n; i++)
    {
        b = 1;
        for(int j = 0; b && PrimeTable[j] * PrimeTable[j] <= i; j++)
        {
            LC++;
            b = i % PrimeTable[j];
        }
        b ? PrimeTable[ptc++] = i : 0;
    }
}

void MakeTable3(int n)
{
    int i,j;
    ptc = 0;
    memset(bPrime,1,sizeof(bPrime));
    for( i = 2; i < n; i++)
    {
        if(bPrime[i])
        {
            PrimeTable[ptc++] = i;
            for( j = i + i; j < n; j += i)
            {
                LC++;
                bPrime[j] = false;
            }
        }    
    }
}

void MakeTable4(int n)
{
    int i,j;
    ptc = 0;
    memset(bPrime,1,sizeof(bPrime));
    for( i = 2; i < n; i++)
    {
        bPrime[i] ? PrimeTable[ptc++] = i : 0;
        for( j = 0; j < ptc && i * PrimeTable[j] < n; j++)
        {
            LC++;
            bPrime[ i * PrimeTable[j] ] = false;
            //当i%PrimeTable[j] == 0 的时候证明此时PrimeTable[j]为i的最小质因子,为了避免重复筛选,退出循环
            if( i % PrimeTable[j] == 0) break;        
        }
    }
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        LC = 0;
        MakeTable1(n);
        printf("%d %d\n",ptc,LC);
        LC = 0;
        MakeTable2(n);
        printf("%d %d\n",ptc,LC);
        LC = 0;
        MakeTable3(n);
        printf("%d %d\n",ptc,LC);
        LC = 0;
        MakeTable4(n);
        printf("%d %d\n",ptc,LC);
    }
    return 0;
}

讨论:

方法4的复杂度为O(n),从渐进意义上讲应该没有更快的算法了吧,如果谁知道更好的方法请留言。

前三种方法的复杂度我不太会分析,如果有大牛会,望指教。

 

  

posted on 2013-04-15 13:24  十指之间  阅读(1662)  评论(0编辑  收藏  举报

导航