筛素数解法

常用的筛素数的算有两种:

1). Eratosthenes筛法:把[1,N]素数p的倍数筛出去,剩余的就是素数。

int prime[N], np;
bool vis[N];
void get_prime()
{
    np = 0;
    memset(vis, 0, sizeof(vis));
    for(int i = 2; i < N; ++i)
    {
        if (!vis[i])
        {
            prime[np++] = i;
            for(int j = i+i; j < N; j +=i) vis[j] = 1;
        }
    }
}

算法复杂度O(N*log log N)

2). 线线筛法:Eratosthenes筛法会有很多重复的筛选,此算法是对Eratosthenes筛法的改进.

线性筛素数的基本思想是:每个合数只被筛一次,将被其最大因数筛掉。

假设我们依据flag数组从小到大判断每个数是否是素数,如果当前该数还未被筛掉,那么就是素数,因为在比它小的数中没有发现因数,将素数加入素数表中。对每一个数i(不论素数或合数),用它筛掉flag数组中以它为最大因数的数。因为每个数只去筛以它为最大因数的数,所以每个合数只会被一个数筛,就是它的最大因数,以此达到线性的复杂度。

假设当前的数是i。以i为最大因数的数是哪些呢?这些数必然是i乘上一个比它小的素数(如果该数是i乘上一个比它大的素数,显然i不会是该数的最大因数;如果是i乘上一个合数x = p1*p2*...*pk (pi为素数),显然通过将x的一些素因数与i相乘会得到比i大的因数)。

假设i可以表示为素数乘积:i = p1*p2*...*pn,x是一个比i小的素数(x显然已经被筛出来了,在我们的素数表中),其中i最小的素因数是p1。i只有与当前素数表中p<=p1的素数相乘,得到的数y才以i为最大因数。反证:如果i乘上pm得到y = i*pm,且pm>p1,那么y有因数y/p1 > i = y/pm。

所以对每一个数i,乘上素数表中不大于i的最小素因数p1的素数,将得到的数从flag数组中筛去,我们就可以在线性的时间复杂度下得到一个素数表。

int prime[N], np;
bool vis[N];
void get_prime2()
{
    np = 0;
    memset(vis, 0, sizeof(vis));
    for (int i = 2; i < N; ++i)
    {
        if (!vis[i]) prime[np++]=i;
        for (int j = 0,t ; j < np && (t = prime[j]*i) < N; ++j)
        {
            vis[t] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}
在该算法中,每个合数都只被最小的素数筛去,算法复杂度O(N)

线性筛法思路解析摘自:http://www.cnblogs.com/luna-lovegood/archive/2012/07/13/2589788.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值