素数筛进阶(二)线性筛算法

线性筛算法思想

image-20210109145606397

- 用最小素因数和一个整数去标记这个合数;

prime[]数组中的素数是递增的,当i能整除prime[j],那么i* prime[j+1] 这个合数肯定被prime[j] 乘以某个数筛掉。因为i中含有 prime[j] , prime[j] 比 prime[j+1] 小,即 i=k*prime[j]
那么i * prime[j+1]=(k*prime[j]) *prime[j+1]=k*prime[j],接下去的素数同理。所以不用筛下去了。因此,在满足 i%prime[j] == 0 这个条件之前以及第一次满足改条件时, prime[j] 必定是 prime[j]*i 的最小因子。

线性筛代码实现
#include<stdio.h>
#define MAX_N 200000

int prime[MAX_N+5];

void init(){
    for (int i =2 ; i <= MAX_N; i++) {
        if (!prime[i]) prime[++prime[0]] = i;//将第i个素数存在prime[i]中;
        for (int j = 1 ; j <= prime[0]; ++j) {
            if (prime[j]*i > MAX_N) break;
            prime[prime[j]*i] = 1;//将合数标记为1;
            if (i % prime[j] == 0) break;//i相当于M;prime[j]最小素因数;
        }
    }
    return ;
}

int main() {
    init();
    printf("%d\n", prime[10001]);
    return 0;
}


关键之处在:if(i%prime[j]==0) break;

这句代码保证了每个数最多被筛一次,将时间复杂度降到了线性。

证:prime[]数组中的素数是递增的,当i能整除prime[j],那么iprime[j+1]这个合数肯定会被prime[j]乘以某个数筛掉。因此,这里直接break掉,将iprime[j+1]及之后的给后面的数去筛。这种方法能保证每个数只被筛一遍,又能保证每个数都被筛到。

  • 为了更好的理解,画出前面几次筛的情况:
    在这里插入图片描述
    从图上我们看到,第一列筛掉的是最小素因子是2的数,第二列筛掉的是最小素因子为3的数,依次类推,可以把所有的合数都筛掉。

因为是按照最小素因子筛选,每个数的最小素因数只有一个,所以可以保证每个数都只会被筛一遍。

例如,i=6 时,第一个素数是2,能整除,筛掉12后就break;至于第二个素数3,6x3中的最小素因数肯定是前一个素数2,所以它要到 i=9,素数取2时才被筛掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值