从埃氏筛到欧拉筛:深入剖析线性筛法的演进与性能飞跃

1. 初识素数筛法:从暴力枚举到埃氏筛

第一次接触素数筛选算法时,很多人都会从最朴素的暴力枚举开始。比如判断数字n是否为素数,就逐个检查2到√n之间的整数能否整除n。这种方法在小范围内勉强可用,但当需要找出1到100万之间的所有素数时,效率就低得令人难以忍受了。

埃拉托斯特尼筛法(简称埃氏筛)的出现,让素数筛选效率提升了一个数量级。记得我第一次实现埃氏筛时,被它的简洁性惊艳到了——只需要一个布尔数组和两个嵌套循环,就能高效筛选素数。核心思想就像筛沙子:先把所有数标记为"可能是素数",然后从小到大,遇到素数就筛掉它的所有倍数。

// 经典埃氏筛实现
const int MAX = 1e6;
bool is_prime[MAX];

void eratosthenes() {
    memset(is_prime, true, sizeof(is_prime));
    is_prime[0] = is_prime[1] = false;
    
    for (int i = 2; i*i < MAX; i++) {
        if (is_prime[i]) {
            for (int j = i*i; j < MAX; j += i) {
                is_prime[j] = false;
            }
        }
    }
}

这个算法有两个精妙之处:一是从i²开始筛,因为更小的倍数已经被更小的素数筛过了;二是外层循环只需要到√n,因为更大的数的倍数都会超出范围。但实际使用中我发现,当处理1亿以上的数字时,埃氏筛开始显现出明显的性能瓶颈。

2. 埃氏筛的局限性与重复筛选问题

在项目实践中,我发现埃氏筛最大的问题是会重复标记合数。比如数字12会被2和3各标记一次,30会被2、3、5各标记一次。这种重复操作随着数据规模增大而愈发严重,导致时间复杂度虽然是O(n log log n),但常数项很大。

举个具体例子:当筛选1到100的数字时:

  • 数字6被
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值