news 2026/8/31 10:40:13

GESP C++考试五级语法知识(二、埃氏筛和线性筛)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GESP C++考试五级语法知识(二、埃氏筛和线性筛)

🌟《素数王国的两种超级筛子》

故事前言:

1、在数字王国里,国王需要一份素数名单

(1)比如:

1 ~ 30 之间的所有素数

(2)答案应该是:

2 3 5 7 11 13 17 19 23 29

(3)问题来了:

如果数字很大,比如:

1 ~ 1,000,000

(4)一个一个判断素数就会非常慢


2、于是王国发明了两种神器:

1️⃣埃氏筛(Eratosthenes Sieve)
2️⃣线性筛(Euler Sieve)

今天我们就来学习这两个神器。


第一部分:埃氏筛法(筛沙子)

🌾故事:筛沙子找金子

小C来到一条河边。

河里有很多沙子(合数)金子(素数)

工人拿来一个大筛子

每发现一个素数,就把它的倍数全部筛掉!

这样剩下的就都是素数。


一、筛法思想

1、假设我们要找

1 ~ 30 的素数

2、先把所有数写出来:

2 3 4 5 6 7 8 9 10 11 ... 30

3、我们准备一个数组:

isPrime[i]

4、表示:

i 是否是素数

5、开始全部设为:

true

二、开始筛

1、第一步:2 是素数

(1)因为 2 没被划掉。

于是:

2 的倍数全部划掉

4 6 8 10 12 14 16 18 20 22 24 26 28 30

(2)剩下:

2 3 5 7 9 11 13 15 17 19 21 23 25 27 29

2、第二步:3 是素数

因为 3 没被划掉。

划掉:

6 9 12 15 18 21 24 27 30

3、第三步:5 是素数

划掉:

10 15 20 25 30

最后剩下:

2 3 5 7 11 13 17 19 23 29

这些就是素数。


三、为什么只筛到 √n?

(1)比如

n = 100

(2)如果一个数是合数:

a × b = n

(3)那么一定有:

一个 ≤ √n 一个 ≥ √n

(4)所以只要筛到:

i * i <= n

就可以了。


四、埃氏筛 C++模板

#include <iostream> using namespace std; const int N = 1000000; bool isPrime[N]; int main() { int n; cin >> n; for(int i=2;i<=n;i++) isPrime[i]=true; for(int i=2;i*i<=n;i++) { if(isPrime[i]) { for(int j=i*i;j<=n;j+=i) isPrime[j]=false; } } for(int i=2;i<=n;i++) if(isPrime[i]) cout<<i<<" "; }

五、为什么从 i*i 开始?

(1)很多同学会问:

为什么不是:

2*i

(2)例如:

i = 5

(3)5 的倍数:

10 15 20 25

(4)向前看一下:

10 已经被 2 删过 15 已经被 3 删过 20 已经被 2 删过

(5)所以:

从 25 开始可以节省时间

也就是:

i * i

六、埃氏筛时间复杂度

大约是:

O(n log log n)

已经非常快了。


第二部分:线性筛

我们见到了一个更厉害的科学家,他叫欧拉。

他说:

我有一种方法,可以让每个合数只被删一次!

这就是:

线性筛(Euler筛)


一、线性筛思想

核心思想:

每个合数 = 最小质因数 × 另一个数

只用最小质因数来筛掉它。

这样就不会重复删除。


二、例子(还是1~30)

我们一边走一边记录素数表


1、i = 2

2 是素数

加入素数表:

prime = {2}

筛:

2×2 = 4

2、i = 3

3 是素数

prime = {2,3}

筛:

3×2 = 6 3×3 = 9

3、i = 4

4 已经被删

不是素数

但继续筛:

4×2 = 8

4、i = 5

5 是素数

prime = {2,3,5}

筛:

5×2 = 10 5×3 = 15 5×5 = 25

5、就这样一直继续。

每个合数只被最小质因数筛一次


三、线性筛 C++模板

#include <iostream> using namespace std; const int N = 1000000; int prime[N]; bool vis[N]; int main() { int n; cin >> n; int cnt = 0; for(int i=2;i<=n;i++) { if(!vis[i]) prime[cnt++] = i; for(int j=0;j<cnt && i*prime[j]<=n;j++) { vis[i*prime[j]] = true; if(i%prime[j]==0) break; } } for(int i=0;i<cnt;i++) cout<<prime[i]<<" "; }

四、为什么要 break?

1、关键一句:

if(i % prime[j] == 0) break;

2、意思是:

如果:

prime[j]

已经是i 的最小质因数


3、那:

i × 更大的质数

就不是最小质因数分解了。

所以必须停止。


4、这样保证:

每个合数只被筛一次


五、时间复杂度

线性筛:

O(n)

是真正的线性时间


六、两种筛法对比

方法原理复杂度
埃氏筛删除倍数O(n log log n)
线性筛最小质因数O(n)

七、理解区别

1、埃氏筛

(1)特点:

一个合数会被删除很多次

(2)例如

30

(3)会被:

2删 3删 5删

2、线性筛

(1)特点:

每个合数只删除一次

(2)例如:

30 = 2 × 15

只由2删除。


八、什么时候用哪种筛法?

1、小数据

n ≤ 10^6

用:

埃氏筛

简单好写。


2、大数据

n ≤ 10^7 或更大

用:

线性筛

更快。


九、最重要的理解总结

(1)埃氏筛

思想:

发现素数 → 删除倍数

(2)线性筛

思想:

用最小质因数删除合数

十、一句话记忆

(1)埃氏筛:

素数 × 所有倍数

(2)线性筛:

每个合数只筛一次

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 17:20:32

序:Hello, Robot!

具身智能&#xff08;Embodied AI&#xff09;&#xff0c;是2026年最硬核、最性感、但也最容易让人一头雾水的赛道。每天都有新的论文砸向 Arxiv&#xff0c;硅谷的初创公司融资新闻刷屏&#xff0c;但很少有人能给你一套从硬件到算法、从传统到SOTA的、系统化的技术全栈梳理。…

作者头像 李华
网站建设 2026/7/14 17:20:33

用Matlab玩转决策分类树:从构建到可视化

Matlab算法&#xff1a;决策分类树&#xff0c;给你的数据画棵树 Matlab算法&#xff1a;建立决策分类树&#xff0c;根据节点和层剪个枝&#xff0c;决策树模型可视化&#xff0c;赶紧把这棵树带回家。 数据程序分开&#xff0c;便于使用&#xff0c;注释详细&#xff0c;注意…

作者头像 李华
网站建设 2026/7/14 17:20:33

【Linux文件系统】Linux文件系统与设备驱动

普通文件、目录、硬盘、U盘、键盘、显示器&#xff0c;甚至进程信息和网络连接…… 在Linux看来&#xff0c;它们统统都可以被抽象成一个可以打开、读写、关闭的“文件”。这样做的好处是统一了接口。对于应用程序员来说&#xff0c;他不需要知道操作的对象到底是什么&#xff…

作者头像 李华
网站建设 2026/7/14 17:20:45

自动化——2.Python进阶——函数

Python进阶函数内置函数自定义函数解包匿名函数回调函数函数 函数介绍&#xff1a; 1.函数是一段代码的组合&#xff0c;用来实现具体的功能 2.内置函数可以直接调用 3.自定义函数可以根据业务需要设计不同的实现代码 内置函数 内置函数可以直接调用&#xff0c;例如print()函…

作者头像 李华
网站建设 2026/7/14 17:20:45

安装Docker ce

文章目录 一、前置准备 二、在线安装完整步骤 步骤1:安装基础依赖工具 步骤2:添加Docker官方GPG密钥 步骤3:配置Docker官方源(国内适配阿里云镜像源) 步骤4:安装Docker CE及配套组件 步骤5:启动并验证Docker 步骤6:(可选)配置非root用户免sudo执行Docker 步骤7:修改…

作者头像 李华
网站建设 2026/7/14 17:20:44

【脉宽调制DCDC功率变换学习笔记003】Buck变换器

1、降压DCDC变换器SPDT开关将输人电压Vs转换为矩形波作为理想低通滤波器的输人&#xff0c;如图 3.1所示。将进行傅里叶变换展开&#xff0c;可表示为直流分量和正弦谐波曲线的和&#xff1a;(3.3)式中&#xff0c;为直流分量&#xff1b;为的基频。直流分量为的平均值。(3.4)若…

作者头像 李华