首页 > 编程语言 >线性筛与埃氏筛算法详解

线性筛与埃氏筛算法详解

时间:2024-12-26 09:28:30浏览次数:3  
标签:prime 埃氏 self 素数 算法 详解 线性

目录

线性筛与埃氏筛算法详解


第一部分:线性筛与埃氏筛算法概述

1.1 什么是埃氏筛算法?

埃氏筛(Sieve of Eratosthenes)是一个古老且高效的算法,用于找出小于给定正整数 N N N 的所有素数。该算法的主要思想是从2开始,依次将每个素数的倍数标记为非素数,直到筛选完所有小于 N N N 的数。

1.2 什么是线性筛算法?

线性筛算法是一种改进版本的埃氏筛算法,它通过引入筛选的顺序来避免重复标记,从而提高了效率。在线性筛中,每个素数的倍数只会被其对应的素数标记一次,避免了埃氏筛中重复标记倍数的情况。

1.3 埃氏筛与线性筛的比较
  • 时间复杂度

    • 埃氏筛的时间复杂度为 O ( N log ⁡ log ⁡ N ) O(N \log \log N) O(NloglogN),在大多数情况下是非常高效的。
    • 线性筛的时间复杂度为 O ( N ) O(N) O(N),它的效率更高,尤其是在处理较大范围的素数时。
  • 空间复杂度

    • 两者的空间复杂度都为 O ( N ) O(N) O(N),因为都需要一个长度为 N N N 的布尔数组来存储每个数是否为素数。
1.4 应用场景
  • 素数分解:计算一个大数的素因数分解时,可以通过筛选出所有小于该数的素数来加速过程。
  • 数论问题:在解决数论问题时,素数是一个核心元素,埃氏筛和线性筛能有效帮助生成素数集合。
  • 密码学:素数在RSA加密等密码学算法中广泛使用,筛选素数是其中的重要步骤。

第二部分:埃氏筛算法原理与实现

2.1 埃氏筛算法原理

埃氏筛算法的基本思想是:从2开始,依次将每个素数的倍数标记为非素数,最终剩下的所有数字就是素数。

2.2 埃氏筛算法的步骤
  1. 初始化一个大小为 N N N 的布尔数组 is_prime,其中所有元素初始值为 True,表示所有数都假设是素数。
  2. is_prime[0]is_prime[1] 设置为 False,因为0和1不是素数。
  3. 从2开始,遍历每个数字 p p p :
    • 如果 is_prime[p]True,说明 p p p 是素数,将其所有倍数(从 p 2 p^2 p2 开始)标记为 False
    • 如果 is_prime[p]False,则跳过这个数。
  4. 遍历结束后,数组中所有值为 True 的索引就是素数。
2.3 埃氏筛的Python实现
class SieveOfEratosthenes:
    def __init__(self, n):
        self.n = n
        self.is_prime = [True] * (n + 1)
        self.is_prime[0] = self.is_prime[1] = False

    def sieve(self):
        for p in range(2, int(self.n ** 0.5) + 1):
            if self.is_prime[p]:
                for i in range(p * p, self.n + 1, p):
                    self.is_prime[i] = False

    def get_primes(self):
        return [i for i in range(2, self.n + 1) if self.is_prime[i]]

# 使用示例
n = 100
sieve = SieveOfEratosthenes(n)
sieve.sieve()
print(sieve.get_primes())
2.4 代码解释
  • SieveOfEratosthenes:该类封装了埃氏筛算法,初始化时接收一个参数 n n n(筛选范围)。sieve() 方法实现了埃氏筛的核心算法,而 get_primes() 方法返回所有小于等于 n n n 的素数。

  • 时间复杂度:由于每个数只会被标记一次,因此时间复杂度是 O ( N log ⁡ log ⁡ N ) O(N \log \log N) O(NloglogN)。


第三部分:线性筛算法原理与实现

3.1 线性筛算法原理

线性筛算法的优化思路在于避免对已经筛选过的数重复标记。在埃氏筛中,对于每个素数 p p p,我们会将其倍数标记为非素数,但是重复标记会浪费时间。线性筛通过严格的顺序控制,确保每个倍数只被素数本身标记一次,从而减少了不必要的计算。

3.2 线性筛算法的步骤
  1. 初始化一个大小为 N N N 的布尔数组 is_prime,所有元素初始化为 True
  2. 遍历每个数 p p p:
    • 如果 p p p 是素数(is_prime[p] == True),则将 p p p 标记为素数。
    • 然后,遍历 p p p 的所有倍数 p × i p \times i p×i,标记 p × i p \times i p×i 为非素数,并确保仅当 p ≤ i p \leq i p≤i 时才进行标记。这样就避免了重复标记。
  3. 最终,所有 True 的位置即为素数。
3.3 线性筛的Python实现
class LinearSieve:
    def __init__(self, n):
        self.n = n
        self.is_prime = [True] * (n + 1)
        self.is_prime[0] = self.is_prime[1] = False
        self.primes = []

    def sieve(self):
        for p in range(2, self.n + 1):
            if self.is_prime[p]:
                self.primes.append(p)
            for prime in self.primes:
                if p * prime > self.n:
                    break
                self.is_prime[p * prime] = False
                if p % prime == 0:
                    break

    def get_primes(self):
        return self.primes

# 使用示例
n = 100
sieve = LinearSieve(n)
sieve.sieve()
print(sieve.get_primes())
3.4 代码解释
  • LinearSieve:与埃氏筛类似,LinearSieve 类封装了线性筛算法。sieve() 方法通过优化的方式进行素数筛选,get_primes() 返回所有素数。

  • 时间复杂度:线性筛的时间复杂度为 ( O(N) ),比埃氏筛更高效。


第四部分:线性筛与埃氏筛的优化比较与应用

4.1 埃氏筛与线性筛的对比
  • 时间效率:线性筛比埃氏筛更高效,尤其在处理大范围的素数时。埃氏筛在筛选每个素数的倍数时,可能会重复筛选,而线性筛通过严格的筛选顺序避免了这种重复。

  • 内存消耗:两者的内存消耗基本相同,都是 ( O(N) ),因为它们都需要一个布尔数组来存储素数信息。

4.2 应用案例
4.2.1 求解素数分解

对于一个大整数,首先利用线性筛筛选出所有小于该数的素数,然后通过这些素数进行素因数分解。

def prime_factors(n, sieve):
    factors = []
    for prime in sieve.get_primes():
        if prime * prime > n:
            break
        while n % prime == 0:
            factors.append(prime)
            n //= prime
    if n > 1:
        factors.append(n)
    return factors

# 使用线性筛求素因数
n = 56
sieve = LinearSieve(100)
sieve.sieve()
print(prime_factors(n, sieve))
4.2.2 密码学应用

在RSA等加密算法中,素数的生成至关重要。线性筛可以帮助快速生成大范围的素数集合,供加密算法使用。

# 使用线性筛生成100

以内的素数
n = 100
sieve = LinearSieve(n)
sieve.sieve()
print("生成的素数集合:", sieve.get_primes())

第五部分:总结与展望

5.1 总结

通过本文的讲解,我们详细了解了埃氏筛和线性筛算法的原理、实现方式及其优化。两者都是非常高效的素数筛选算法,其中线性筛在优化上相较于埃氏筛更为高效,尤其是在处理较大范围时,线性筛可以避免不必要的重复计算。

5.2 展望

随着算法优化的不断发展,未来的素数筛选算法可能会在时间复杂度和空间复杂度上进行进一步改进。特别是在大数据领域,如何更高效地筛选素数,成为了一个非常重要的研究方向。

在应用方面,素数筛选算法在密码学、数论计算等领域有着广泛的应用,未来随着计算力的提升和算法的优化,更多复杂的素数相关问题将得到高效解决。

标签:prime,埃氏,self,素数,算法,详解,线性
From: https://blog.csdn.net/qq_42568323/article/details/144628710

相关文章

  • 图像边缘检测与轮廓提取详解及python实现
    目录图像边缘检测与轮廓提取详解第一部分:图像边缘检测与轮廓提取概述1.1什么是边缘检测和轮廓提取?1.2边缘检测与轮廓提取的应用领域1.3为什么需要边缘检测和轮廓提取?第二部分:常见的图像边缘检测算法2.1Sobel算子2.2Canny边缘检测2.3拉普拉斯算子(LaplacianofGaus......
  • ThreeJs-083D动画系统详解
    一.动画原理和应用three的动画大概就是通过不同时间的关键帧来实现加载一个手机模型在这个对象里面,注意后期都是直接通过可视化软件Blender编辑好关键帧就能实现动画,这也是个已经编辑好的动画模型,在这个对象里面有一个animations就是动画集,也就是这个物体可以有很多个动画其......
  • 基于springboot+推荐算法的智能书店系统
    博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有实实在在的写点程序。......
  • 基于EO平衡优化器算法的目标函数最优值求解matlab仿真
    1.程序功能描述基于EO平衡优化器算法的目标函数最优值求解matlab仿真。提供九个测试函数,分别对九个测试函数仿真输出最优解以及对应的优化收敛曲线。2.测试软件版本以及运行结果展示MATLAB2022A版本运行  3.核心程序whilej2<Niters%主循环进行迭代%时......
  • “高精度算法”思想 → 大数阶乘
    【“大数阶乘”算法思想】利用“高精度算法”思想计算“大数阶乘”,需要明确几个关键点:(1)数组a的大小(maxn)需要足够大,以存储阶乘结果的所有位数。(2)数组a应该在函数外部被初始化为全零,并且第一个元素应该设置为1,表示阶乘的初始值。(3)在计算过程中,数组a的每一位都会被更新......
  • Go init()使用详解
    持续创作,加速成长!这是我参与「掘金日新计划·10月更文挑战」的第1天,点击查看活动详情1.init()的使用见名知意,init()是Go中的初始化函数。我们都知道,main()函数是Go程序启动的入口,而init()函数就是在main()之前,起到一个初始化的作用。 Go代码解读复制代码packag......
  • 大二上 数据结构与算法 课堂模板算法 20241225
    数据结构与算法1-基本数据结构2-分治策略3-堆4-排序5-选择&树6-搜索树&散列表&并查集6.1-搜索树6.2-散列表6.3-并查集intfind(intx){if(pre[x]==x)returnx;returnpre[x]=find(pre[x]);}voidjoin(intx,inty){intfx=find(x)......
  • 常见字符串算法简记(持续更新中)
    包含KMP(border相关,KMP自动机),Manacher,Zalgorithm(exKMP),SuffixArray的简单记录。当然写的很烂,欢迎当玩笑看。0.前言1.记一忘三二本文所写的字符串算法都基于一个基本思想:充分利用已知信息的性质加速求出所求信息的过程。这是老生常谈的。因此在这些算法的复杂度分析中主要......
  • CSRF跨站请求伪造攻击详解
    一、CSRF攻击概述1.1CSRF攻击定义用户浏览器加载恶意网站时,浏览器中的恶意网站页面向另一目标网站自主发起一个恶意HTTP请求,该攻击方式即为CSRF攻击。1.2CSRF攻击的本质在CSRF攻击中,攻击者诱使用户的浏览器发起一个恶意请求,本质上是借助用户的凭证,以用户的身份去执行特......
  • 嵌入式单片机中串口通信实现详解
    串口通信的概念通信的概念通信指的是CPU和外部设备之间或者计算机与计算机之间的数据交互。                  通信的种类处理器与外部设备之间的通信方式有两种:   串行通信            并行通信      ......