news 2026/9/28 20:26:48

GESP2026年9月认证C++五级( 第三部分编程题(1、哥德巴赫猜想))精讲

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GESP2026年9月认证C++五级( 第三部分编程题(1、哥德巴赫猜想))精讲



一、先把题目变成一个“小侦探故事” 🔍

假设老师给小明一个数字:

10

问:

10 可以由多少种不同的“两个素数之和”组成?

我们知道:

10 = 3 + 7 10 = 5 + 5

所以答案是:

2

而且:

3 + 7 7 + 3

是按照同一种方法。

题目明确规定:

只有两个分解方案中的素数集合不同,才算不同方案。

所以我们不能把:

3 + 7 7 + 3

算成两次。


二、这道题真正问的是什么?

我们可以把问题浓缩成一句话:

给你一个偶数 n,找出所有满足p + q = n的素数对(p,q),而且每一对只能计算一次。

例如:

n = 10

尝试:

2 + 8 3 + 7 4 + 6 5 + 5

其中:

  • 2 是素数,但 8 不是 ❌

  • 3 是素数,7 也是素数 ✅

  • 4 不是素数 ❌

  • 5 是素数,5 也是素数 ✅

所以:

10 = 3 + 7 10 = 5 + 5

答案:

2

三、第一关:什么是素数?⭐

一个大于 1 的整数:

只能被 1 和它自己整除

就是素数。

例如:

2 √ 3 √ 4 × 5 √ 6 × 7 √ 8 × 9 × 10 × 11 √

所以:

2 3 5 7 11

都是素数。


四、如果一个一个判断素数,可以吗?

当然可以。

比如我们枚举:

2 3 4 5 ... n/2

然后判断:

i 是不是素数? n-i 是不是素数?

如果两个都是素数:

ans++;

就可以了。

但是问题来了:

如果 n 很大呢?

如果每次都重新判断一个数是不是素数,就可能重复做大量工作。

所以这道题的漂亮解法是:

⭐ 先把所有素数一次性找出来!

这就是:

埃氏筛——筛素数


五、埃氏筛:像筛面粉一样筛掉合数

我们准备一个数组:

bool not_prime[1000005];

它的含义是:

not_prime[x] == true

表示:

x 不是素数。

反过来:

not_prime[x] == false

表示:

x 目前还是“素数候选人”。

可以把它想象成:

🌟 一开始所有数字都参加“素数选拔赛”,然后我们不断把合数淘汰掉。


六、筛素数第一步:1 不是素数

程序:

not_prime[1] = true;

因为:

1

不是素数。


七、从 2 开始检查

参考程序:

for (int i = 2; i <= n; ++i) { if (!not_prime[i]) { primes[pcnt++] = i; for (int j = 2; i * j <= n; ++j) { not_prime[i * j] = true; } } }

我们一步一步看。


八、遇到 2:发现 2 是素数

因为:

not_prime[2] == false

所以:

2 是素数

把它保存:

primes[pcnt++] = 2;

然后把 2 的倍数全部标记成合数:

2×2 = 4 2×3 = 6 2×4 = 8 2×5 = 10 ...

于是:

4 × 6 × 8 × 10 × ...

都被淘汰。


九、遇到 3

3 还没有被标记:

not_prime[3] == false

所以:

3 是素数

保存:

primes = {2,3}

然后把:

3×2 = 6 3×3 = 9 3×4 = 12 ...

标记成合数。


十、遇到 4

这时候:

not_prime[4] == true

说明:

4 已经被 2 淘汰

所以:

if (!not_prime[i])

不成立。

直接跳过。


十一、最后得到一个“素数通讯录”

比如:

n = 20

最后:

primes = 2 3 5 7 11 13 17 19

这就是我们的素数名单。

参考程序就是先通过get_primes()完成这件事情。


十二、第二关:找到两个素数

现在假设:

n = 20

我们已经知道:

2 3 5 7 11 13 17 19

都是素数。

那么我们要寻找:

p + q = 20

例如:

2 + 18 ❌ 3 + 17 ✅ 5 + 15 ❌ 7 + 13 ✅ 11 + 9 ❌

所以:

20 = 3 + 17 20 = 7 + 13

答案:

2

十三、为什么只枚举到 n/2?

这是这道题最重要的一个小技巧。

参考程序:

primes[i] <= n / 2

为什么?

假设:

n = 20

如果我们枚举到:

11

那么:

20 - 11 = 9

这已经超过一半了。

而前面其实已经检查过:

20 = 9 + 11

所以再检查:

11 + 9

就是重复计算。


十四、这就是“去重”的秘密 ⭐⭐⭐

假设:

n = 10

如果我们全部枚举:

2 + 8 3 + 7 4 + 6 5 + 5 6 + 4 7 + 3 8 + 2

你会发现:

3 + 7 7 + 3

重复了。

所以我们只检查:

p <= n/2

也就是:

p <= 5

只需要:

2 + 8 3 + 7 4 + 6 5 + 5

这样:

3 + 7

出现一次。

7 + 3

根本不会再出现。

这就是一种非常重要的:

“只枚举一半,自动避免重复”


十五、程序中这一句非常关键

参考程序:

for (int i = 0; i < pcnt && primes[i] <= n / 2; ++i)

可以拆成:

i < pcnt

表示:

还没有走完素数数组。

以及:

primes[i] <= n / 2

表示:

只检查前一半的素数。


十六、然后检查另一个数字是不是素数

程序:

if (!not_prime[n - primes[i]]) ans++;

这句话看起来有点吓人,我们翻译成“小学生语言”:

假设:

n = 20 primes[i] = 7

那么另一个数字就是:

20 - 7 = 13

程序检查:

!not_prime[13]

因为:

13 是素数

所以:

not_prime[13] = false

那么:

!false = true

于是:

ans++;

答案加 1。


十七、完整走一遍 n = 20

我们来做一张“侦探表”。

第一个素数第二个数20-p是素数吗?算不算
218❌不算
317✅✅
515❌不算
713✅✅
119❌不算

所以:

20 = 3 + 17 20 = 7 + 13

答案:

2

十八、再看一个 n = 28

素数:

2 3 5 7 11 13 17 19 23

只检查:

p <= 14

于是:

2 + 26 ❌ 3 + 25 ❌ 5 + 23 ✅ 7 + 21 ❌ 11 + 17 ✅ 13 + 15 ❌

所以:

28 = 5 + 23 28 = 11 + 17

答案:

2

十九、现在来看完整参考程序

参考程序核心结构是:先筛素数,再枚举不超过n/2的素数,并检查n-primes[i]是否也是素数。

#include <cassert> #include <cstdio> using namespace std; int n, ans; bool not_prime[1000005]; int primes[500000], pcnt = 0; void get_primes() { not_prime[1] = true; for (int i = 2; i <= n; ++i) { if (!not_prime[i]) { primes[pcnt++] = i; for (int j = 2; i * j <= n; ++j) { not_prime[i * j] = true; } } } } int main() { scanf("%d", &n); get_primes(); for (int i = 0; i < pcnt && primes[i] <= n / 2; ++i) { if (!not_prime[n - primes[i]]) ans++; } printf("%d\n", ans); return 0; }

二十、把程序分成“三个房间” 🏠

其实程序只有三个任务。

🏠 房间1:输入

scanf("%d", &n);

得到:

n

🏠 房间2:制作素数名单

get_primes();

完成:

2 3 5 7 11 13 ...

🏠 房间3:寻找答案

for (...) if (...) ans++;

也就是:

找到一个素数p,再看看n-p是不是素数。


二十一、同学们一定要理解的核心思想

这道题千万不要只记代码。

应该记住下面这个“魔法公式”:

⭐ 核心公式

如果:

n = p + q

那么:

q = n - p

所以:

枚举一个素数 p,只需要检查 n-p 是不是素数。

而为了避免:

p + q q + p

重复:

只枚举p <= n/2。


二十二、为什么这道题需要“筛素数”?

假如我们要检查:

n - p

是不是素数。

如果每次都从 2 开始试除:

2 3 4 5 ...

会比较慢。

于是我们提前做一次:

埃氏筛

把:

2~n

里面所有素数找出来。

以后判断:

not_prime[x]

就可以:

O(1)

知道它是不是素数。

这就是算法思想中的:

“先预处理,再快速查询”


二十三、最容易犯的 4 个错误 ⚠️

错误1:把p+q和q+p算两次

例如:

3+7 7+3

不能算两次。

解决办法:

primes[i] <= n / 2

只枚举一半。


错误2:忘记 1 不是素数

程序:

not_prime[1] = true;

就是为了明确告诉计算机:

1 ❌

错误3:看到!not_prime就晕

记住:

not_prime[x] = true

意思:

x 不是素数。

所以:

!not_prime[x]

就是:

x 是素数。

可以把它翻译成:

“不是非素数”

也就是:

“是素数”

错误4:只判断 p 是素数

例如:

20

看到:

7

是素数就直接ans++,这是错的。

必须同时保证:

7 是素数 20-7=13 也是素数

两个都成立,才能算一种方案。


二十四、这道题的“万能思维模板” 🧠

以后遇到类似题目,可以按照这个顺序思考:

第一步:题目要找什么?

p + q = n

第二步:能不能枚举一个?

可以。

枚举:

p

然后:

q = n-p

第三步:怎么快速判断 q?

提前:

筛素数

第四步:如何避免重复?

只枚举:

p <= n/2

第五步:找到一组合法方案怎么办?

ans++;

二十五、最后送大家一句“考场口诀” 🎯

先筛素数,名单做好;
枚举一半,避免重复;
q = n-p,两个都素;
找到一组,答案加一!


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

十八岁的第一个博客

我现在是一个民办二本的大一新生&#xff0c;刚刚高考结束来到这个憧憬了十八年的大学校园&#xff0c;我不想在大学四年中用着父母给的生活费浑浑噩噩度过&#xff0c;我想我该长大了&#xff0c;于是我在机缘巧合下认识了鹏哥&#xff0c;他的好多技巧和方法我认为都可以让我…

作者头像 李华
网站建设 2026/9/28 20:25:58

计算机毕业设计选题推荐:基于大数据的豆瓣电影与影评数据可视化与分析、毕业设计选题、选题推荐、高质量项目、毕设指导、项目定制、源码、讲解文档

&#x1f496;&#x1f496;作者&#xff1a;计算机毕业设计小途 &#x1f499;&#x1f499;个人简介&#xff1a;曾长期从事计算机专业培训教学&#xff0c;本人也热爱上课教学&#xff0c;语言擅长Java、微信小程序、Python、Golang、安卓Android等&#xff0c;开发项目包括…

作者头像 李华
网站建设 2026/9/28 20:25:56

等保2.0

等保全称网络安全等级保护2.0是2019年实施的新标准用来替代旧的等保1.0简单来说就是国家给各类信息系统划分不同的安全等级系统越重要需要达到的安全底线就越高一共分为五个等级 一级级别最低一般是个人使用的简单系统被入侵后影响很小由使用单位自行管理 二级属于普通级别大多…

作者头像 李华
网站建设 2026/9/28 20:24:55

Electron 能跑在鸿蒙上?拆解这套把 Node 22 + Chromium 塞进 HAP 的运行时

Electron 能跑在鸿蒙上&#xff1f;你多半会以为是什么套壳方案。 不是。 harmonypc-electron 是真把 Node 22 Chromium 搬进了 HAP——原生 SO 躺在 libs/arm64-v8a/ 里&#xff0c;ArkTS 桥接层负责把鸿蒙的系统能力暴露给 Node。 上篇我说「把 dsh 搬上鸿蒙&#xff0c;只换…

作者头像 李华