埃氏筛和线性筛的比较

在解决涉及素数筛选的问题时,埃氏筛在处理大数据时容易超时。线性筛通过优化避免了多余计算,其时间复杂度为O(N),相比埃氏筛的O(NloglogN)在大数据量下优势明显。对于1e7的数据,线性筛计算次数仅为埃氏筛的约1/2.7,更适合处理大规模问题。建议在算法学习中优先考虑使用线性筛。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这段时间在洛谷上面写题目的时候,发现对于莫比乌斯反演这种题目,以及一些其他的求素数的题目,假如要进行筛素数的时候,用埃氏筛一般都会被T,所以我想对这两种算法进行一个性能的对比。

首先,我们来看到埃氏筛,先给出代码:

//筛出1-n之间的素数
bool vis[1e7]={
   
   false};  //初始化全为false
void Eratosthenes(int n){
   
   
    for(int i=2;i<=n;i++){
   
   
        if(vis[i]==false){
   
     //发现这个是素数
   
<think>嗯,用户想了解埃氏筛法线性筛法的区别及实现。首先,我得回忆一下这两种筛法的基本概念。埃氏筛法我记得是埃拉托斯特尼提出的,用来找出所有小于等于某个数的质数。它的原理是从小到大遍历每个数,如果是质数,就标记它的倍数,比如2是质数,就把4、6、8等标记为合数。这样一步步筛下去。 但用户提到了线性筛法,也就是欧拉筛。线性筛法的目标是每个合数只被标记一次,这样可以减少重复操作,提高效率。埃氏筛法中,像数字6会被23都标记一次,导致重复。而线性筛法通过让每个合数只被最小的质因数筛掉,比如6只会被2筛掉,避免了重复。 接下来需要比较两者的时间复杂度。根据引用中的资料,埃氏筛法优化后的时间复杂度是$O(n\log\log n)$,而线性筛法是$O(n)$。这说明线性筛法在大数据量时更高效。不过实际应用中,埃氏筛法的常数项可能更小,所以在某些情况下可能表现更好。 然后是实现的区别。埃氏筛法实现起来比较简单,可以用一个循环,对每个质数的倍数进行标记。而线性筛法需要维护一个质数列表,并且对于每个数,用当前已知的质数去乘,直到遇到能整除当前质数的数为止,这样可以确保每个合数只被筛一次。 还需要考虑空间复杂度。线性筛法需要额外的空间来存储质数列表,而埃氏筛法只需要一个布尔数组。这可能在小内存环境下有影响,但通常内存足够的话,线性筛法更优。 用户提供的引用里提到,埃氏筛法像用加法筛,而线性筛法用乘法。这可能是指埃氏筛法通过不断加当前质数来标记倍数,而线性筛法则是用已有的质数相乘来生成合数。这点需要明确解释。 另外,引用中提到,埃氏筛法的一个合数n一定有一个小于等于√n的质因子,这可能影响筛法的终止条件。而线性筛法通过最小质因子来确保每个合数被正确标记。 最后,用户可能需要具体的代码示例来理解两者的实现差异。埃氏筛法的代码相对简单,双重循环;而线性筛法需要一个质数列表更复杂的条件判断。代码示例能帮助用户直观看到区别。 总结起来,回答应该包括原理对比、时间复杂度分析、实现方式差异以及各自的优缺点,同时给出代码示例应用场景。需要确保使用正确的中文LaTeX格式,并引用提供的资料。</think>### 埃氏筛法线性筛法对比及实现 #### 一、原理区别 1. **埃氏筛法**: 通过标记质数的倍数筛选合数。例如,找到质数$2$后标记$4,6,8,\dots$;找到质数$3$后标记$6,9,12,\dots$。每个合数可能被多次标记(如$6$被$2$$3$各标记一次),时间复杂度为$O(n \log \log n)$[^3]。 2. **线性筛法**(欧拉筛): 确保每个合数仅被其最小质因数标记一次。例如,$6$只会被质数$2$通过$2 \times 3$标记,而不会在质数$3$时重复标记。时间复杂度优化为$O(n)$[^1]。 #### 二、实现差异 1. **埃氏筛法代码**: ```python def eratosthenes(n): is_prime = [True] * (n+1) primes = [] for i in range(2, n+1): if is_prime[i]: primes.append(i) for j in range(i*i, n+1, i): # 从i²开始标记 is_prime[j] = False return primes ``` - **特点**:简单但存在重复标记,例如$12$会被$2$$3$各标记一次。 2. **线性筛法代码**: ```python def linear_sieve(n): is_prime = [True] * (n+1) primes = [] for i in range(2, n+1): if is_prime[i]: primes.append(i) for p in primes: if i * p > n: break is_prime[i * p] = False if i % p == 0: # 关键:确保p是i*p的最小质因数 break return primes ``` - **特点**:通过`if i % p == 0`终止内层循环,保证每个合数只被最小质因数筛去[^1]。 #### 三、性能对比 | 筛法 | 时间复杂度 | 空间复杂度 | 适用场景 | |------------|---------------|------------|------------------------| | 埃氏筛法 | $O(n \log \log n)$ | $O(n)$ | 小规模数据或快速实现 | | 线性筛法 | $O(n)$ | $O(n)$ | 大规模数据需高效去重 | #### 四、关键优化点 - 埃氏筛法改进:**从$i^2$开始标记**,减少冗余操作[^4]。 - 线性筛法核心:**用最小质因数终止循环**,避免重复标记。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值