区间质数搜索——埃拉托斯特尼筛法和欧拉筛法

news/2024/9/25 20:10:24/文章来源:https://www.cnblogs.com/qinLiCode/p/18432084

参考资料

【中国大学生计算机设计大赛国赛二等奖微课与教学辅助《埃拉托斯特尼筛法》】
【中国大学生计算机设计大赛《素数筛选—欧拉线性筛选法详解》】
Eratosthenes筛法-CSDN博客
【算法/数论】欧拉筛法详解:过程详述、正确性证明、复杂度证明-CSDN博客
水平有限,欢迎交流!

练习题

[编程入门]筛选 N 以内的素数 - C 语言网 (dotcpp. Com)

埃拉托斯特尼筛法算法

思想

步骤

埃拉托斯特尼筛法的基本步骤如下:

  1. 创建一个列表:创建一个从2到n的数字列表。
  2. 标记质数:从列表的第一个数(即2)开始,把它标记为质数。
  3. 筛掉倍数:然后去掉列表中所有2的倍数(除了2本身),因为这些数都是合数。
  4. 移动到下一个未标记的数:接下来,移动到列表中未被标记为合数的下一个数(此时是3),再次标记为质数,并筛掉它的所有倍数。
  5. 重复步骤:重复上述过程,直到根号 n。

优化

代码实现(以 java 为例)

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
    /** 优化埃氏筛法求质数
     * 获取小于等于n的所有质数
     * @param n 最大检查范围
     * @return 返回小于等于n的所有质数的列表
     */
    public static List<Integer> getPrimesBySieve(int n) {
        boolean[] st = new boolean[n + 1];
        List<Integer> primes = new ArrayList<>();
        for (int p = 2; p * p <= n; p++) {
            if (!st[p]) {  // 如果p还没有被标记,则它是质数
                primes.add(p);
                for (int i = p * p; i <= n; i += p) {
                    // 从p的平方开始,依次标记p的倍数
                    st[i] = true;  // 标记p的倍数为合数
                }
            }
        }
        // 添加剩余的大于sqrt(n)的质数
        for (int p = (int)Math.sqrt(n) + 1; p <= n; p++) {
            if (!st[p]) {
                primes.add(p);
            }
        }
        return primes;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Integer> primes = getPrimesBySieve(n);
        for (Integer i : primes) {
            System.out.println(i);
        }
    }
}

欧拉筛法算法思想

思想

欧拉筛法(Euler Sieve)作为一种算法来找出所有小于或等于 n 的质数。欧拉筛法是一种改进的素数筛选法,使得每个合数只由其最小的质因数,它减少了标记合数时的重复工作,提高了效率。

步骤

下面是该方法的步骤归纳:

  1. 初始化:
    • 创建一个布尔数组 st,长度为 n+1,用于标记数字是否为合数
    • 创建一个列表 primes 来存储筛选出的质数。
  2. 遍历从 2 到 n 的所有整数:
    • 对于每一个整数 i,如果 st[i]false(即 i 未被标记为合数),则认为 i 是一个质数,并将 i 添加到质数列表 primes 中。
  3. 标记合数:
    • 使用已经找到的质数列表中的元素 p 来标记合数。对于每一个质数 p,遍历从 i*p 开始的后续合数,并将其在 st 数组中标记为 true
    • 在标记合数的过程中,一旦 i*p 超过 n,则停止进一步的标记。
    • 另外,当 i 能够被 p 整除时(即 i % p == 0),表明 p为p * i的最小质因子,此时可以停止内部循环以避免重复标记。
  4. 返回结果:
    • 完成以上步骤后,返回包含所有质数的列表 primes
      这种筛法的关键在于减少对合数的重复标记次数,使得每个合数只由其最小的质因数来标记一次,从而提高了算法效率。

代码实现(以 java 为例)

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
    public static List<Integer> getPrimesByEulerSieve(int n) {
        boolean[] st = new boolean[n + 1];  // 判断是否是合数
        List<Integer> primes = new ArrayList<>();  // 存储找到的质数
        for (int i = 2; i <= n; i++) {
            if (!st[i]) {  // 如果i没有被标记为合数,则i是质数
                primes.add(i);  // 将i添加到质数列表中
            }
            for (Integer p : primes) {
                if(i*p>n)//越界
                    break;
                st[i * p] = true;  // 标记合数
                /*
                 * 确保每个合数只被它最小的质因数筛除一次
                 * 条件成立此时p为p*i的最小质因子
                 * 如合数12 当发现能被2筛去(12 = 2*6)时,此时终止循环,否则会发现仍会被3筛去(12 = 3*4)
                 */
                if (i % p == 0)
                    break;
            }
        }
        return primes;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Integer> primes = getPrimesByEulerSieve(n);
        for (Integer i : primes) {
            System.out.println(i);
        }
        sc.close();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/803647.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024/9/25代码随想录 图论 关于ACM模式下输出的细节

1. 就只输出一行数据,输出 1 2 4 5 来说,

quixel bridge如何导入unity

bridge如何导入unity# 1.[Quixel Bridge](https://quixel.com/bridge)下载和设置 1. 下载[Quixel Bridge - Manage 3D content and export with one click](https://quixel.com/bridge) 客户端注册 安装。bridge 模型导出路径配置 和 插件下载客户端点击 Edit ->Export Set…

mini-lsm通关笔记Week2Day3

项目地址:https://github.com/skyzh/mini-lsm 个人实现地址:https://gitee.com/cnyuyang/mini-lsmSummary在本章中,您将:实现tiered合并策略并在压缩模拟器上对其进行模拟。 将tiered合并策略纳入系统。我们在本章所讲的tiered合并和RocksDB的universal合并是一样的。我们将…

mini-lsm通关笔记Week2Day2

项目地址:https://github.com/skyzh/mini-lsm 个人实现地址:https://gitee.com/cnyuyang/mini-lsmSummary在本章中,您将: 要将测试用例复制到启动器代码中并运行它们,实现一个simple leveled合并策略,并在合并模拟器上进行仿真。 将compaction作为后台任务启动,并在系统…

指针2)

1.& &是地址符,类型是其后面的类型加一个“*”,任何变量都可以使用&来获取地址,但不能用在常量上。 char a = 10; short b = 20; int c = 30; char*=pa pa=&alea取地址:ebp-4的地址放入eax,再将eax里的地址放入ebp-10里 &可以取任何一个变量…

nssctf(web

web 1.浏览器也能套娃 查看wp,是ssrf漏洞 介绍:SSRF漏洞产生的原因是服务端提供了能够从其他服务器应用获取数据的功能,比如从指定的URL地址获取网页内容,加载指定地址的图片、数据、下载等等。 SSRF的利用:进行内网资源的访问:url?url=http://内网的资源url利用伪协议:…

RTE 大会报名丨AI 时代新基建:云边端架构和 AI Infra ,RTE2024 技术专场第二弹!

所有 AI Infra 都在探寻规格和性能的最佳平衡,如何构建高可用的云边端协同架构?语音 AI 实现 human-like 的最后一步是什么?AI 视频的爆炸增长,给新一代编解码技术提出了什么新挑战?当大模型进化到实时多模态,又将诞生什么样的新场景和玩法?AI 加持下,空间计算和新硬件…

002-QOS基本原理

QOS基本原理QOS概述什么是QOS QoS服务模型 区分服务模型 QoS常用技术 (DiffServ模型) QoS数据处理流程 (DiffServ模型)QoS流分类和流标记QoS数据处理流程 为什么需要流分类和流标记简单流分类外部优先级 - VLAN报文 外部优先级 - MPLS报文 外部优先级 - IP报文 各外部优先级间的…

本地部署运行 Google Gemma 开源大模型

Google 开源了 Gemma 大模型,有 7B 和 2B 两个版本,7B 模型的能力已经是开源模型中的领先水平。Gemma 可以轻松的在本地部署运行,如果你的显存在 8G 以上,可以体验 7B 版本,8G 以下的话可以试试 2B 版本。 部署过程如下: 1、使用 ollama 运行 Gemma 模型 2、使用 Chatbox…

mini-lsm通关笔记Week2Overview

Week 2 Overview: Compaction and Persistence在上周,您已经实现了LSM存储引擎的所有必要结构,并且您的存储引擎已经支持读写接口。在本周中,我们将深入探讨SST文件的磁盘组织,并研究在系统中实现性能和成本效益的最佳方法。我们将花4天时间学习不同的compaction策略,从最…

001-什么是VOQ

1、什么是VOQ(Virtual Output Queues)? VOQ(虚拟输出序列)是一种存储结构,由FIFO与RAM以及逻辑结构组合构成。在一些数据应用场景中能够有效存储数据并且能够及时输出,避免阻塞。一句话来说VOQ的优点在于:共享存储,较少存储资源,避免数据阻塞,提高数据输出效率。 2、…