Eratosthenes筛选法与欧拉筛选法

Eratosthenes筛选法与欧拉筛选法
由于一个合数总是可以分解成若干个质数的乘积,那么如果把质数的倍数都去掉,那么剩下的就是质数了.Eratosthenes筛选法的思想特别简单:对于不超过n的每个非负整数p,删除2p,3p,4p,...,当处理完所有数之后,还没有被删除的就是素数.如果用vis[i]表示i已经被删除,则筛选法的代码可以写成:
void isprime(int n)///筛选1-n的素数
{
    memset(vis,0,sizeof(vis));
    for(int i = 2; i <= n; i++)
        for(int j = 2 * i; j <= n; j += i)
            vis[j] = 1;
}
尽管代码已经相当高效了,但仍然可以进行改进.首先,在"对于不超过n的每个非负数p"中,p可以限定为素数--只需在第二重循环前加一个判断if(!vis[i])即可.另外,内层循环也不必从* 2开始--它已经在= 2时被筛选了.改进后代码如下:
void isprime(int n)///筛选1-n的素数
{
    memset(vis,0,sizeof(vis));
    int m = sqrt(n + 0.5);
    for(int i = 2; i <= m; i++)
    {
        if(!vis[i])
        {
            for(int j = i * i; j <= n; j += i)
                vis[j] = 1;
        }
    }
}

Eratosthenes筛选法虽然效率高,但是Eratosthenes筛选法做了许多无用功,一个数会被筛到好几次,最后的时间复杂度是O(nloglogn),对于普通素数算法而言已经非常高效了,但欧拉筛选法的时间复杂度仅仅为O(n).

欧拉筛选法的思想就是不做无用功,原本Eratosthenes筛法的第一重循环是用来找素数,然后把素数的倍数标记,而欧拉筛法换了一个角度,第一位是找素数没有问题,但是标记的时候用的是所有数.欧拉筛选法在数据小的时候不如Eratosthenes筛选法快,反而是数据变大以后,两者差距变得越来越明显,欧拉筛选法明显快于Eratosthenes筛选法.欧拉筛选法代码如下:

const int Max = 100002;
int Prime[Max];
bool vis[Max];
void prepare()
{
    int num = 0;
    memset(vis,true,sizeof(vis));
    for(int i = 2; i <= Max; ++i)
    {
        if(vis[i])
            Prime[++num] = i;
        for(int j = 1; j <= num; ++j)
        {
            if (i * Prime[j] > Max)
                break;
            vis[i * Prime[j]] = false;
            if (i % Prime[j] == 0)
                break;
        }
    }
}


  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值