重生之我在CSDN学线性筛

线性筛(Linear Sieve)是一种高效的筛选素数的算法,它相对于埃拉托色尼筛法(埃氏筛)在时间复杂度上有显著优化。埃氏筛的时间复杂度是 O(nlog⁡log⁡n)O(n \log \log n),而线性筛将其优化到了 线性时间复杂度 O(n)O(n)

一、基本思想

线性筛的核心思想是:每个合数只被它的最小质因数(最小的那个质数因子)筛掉一次

对比埃氏筛

  • 埃氏筛中每找到一个质数 pp,就用它去筛掉所有 p×kp \times k 的数(其中 k≥pk \ge p)。

  • 线性筛中每找到一个质数 pp,只用它去筛掉所有合数 p×kp \times k,其中 kk 是当前已经处理过的数,并且保证 p≤kp \le k 且 pp 是 kk 的最小质因数。


二、线性筛的实现

代码实现

#include <iostream>
#include <vector>

using namespace std;

const int MAXN = 1e6 + 10;

vector<int> primes;      // 存储所有质数
bool is_composite[MAXN]; // 标记合数

void linear_sieve(int n) {
    for (int i = 2; i <= n; ++i) {
        if (!is_composite[i]) {
            primes.push_back(i); // i 是质数
        }
        for (int p : primes) {
            if (p * i > n) break;
            is_composite[p * i] = true;
            if (i % p == 0) break; // 保证每个数只被其最小质因数筛去
        }
    }
}

int main() {
    int n = 100;
    linear_sieve(n);
    for (int p : primes) {
        cout << p << " ";
    }
    cout << endl;
    return 0;
}

三、核心原理讲解

对于每个整数 ii,我们要用所有比它小的质数 pp 来生成新的合数 i×pi \times p,这要满足两个条件:

  1. p 是质数(由 primes 中维护)。

  2. p 是 i 的最小质因数(也就是说,一旦 i 被 p 整除,就不能再被更大的质数继续乘下去生成合数)。

这样可以保证:

  • 每个合数最多被筛一次。

  • 每个质数只会筛掉有限次合数。

举个例子:

假设我们当前处理到 i=6i = 6,之前筛到的质数有 2,3,52, 3, 5。

  • 先尝试乘以 2:6 * 2 = 12 → 标记为合数

  • 然后乘以 3:6 * 3 = 18 → 标记为合数

  • 然后乘以 5:6 * 5 = 30 → 标记为合数

但注意到当 i=6i = 6 被 2 整除时,我们就不允许之后再用更大的质数去生成合数(比如 6 × 3),以避免重复筛选。


四、时间复杂度分析

每个合数 nn 只会被它的最小质因数 pp 筛掉一次,因此总共不会超过 nn 次筛选。

所以总时间复杂度是 O(n)


五、拓展用法

  1. 计算欧拉函数(φ):可以在线性筛的同时计算每个数的欧拉函数值。

  2. 最小质因数:记录每个合数的最小质因数(可用于质因数分解)。

  3. 莫比乌斯函数(μ):也可以在线性筛过程中一并求出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值