宣传一下 算法提高课整理
CSDN个人主页:更好的阅读体验
原题链接
题目描述
哥德巴赫猜想的内容如下:
任意一个大于 4 4 4 的偶数都可以拆成两个奇素数之和。
例如:
8 = 3 + 5 8 = 3 + 5 8=3+5
20 = 3 + 17 = 7 + 13 20 = 3 + 17 = 7 + 13 20=3+17=7+13
42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23 42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23 42=5+37=11+31=13+29=19+23
现在,你的任务是验证所有小于一百万的偶数能否满足哥德巴赫猜想。
输入格式
输入包含多组数据。
每组数据占一行,包含一个偶数 n n n。
读入以 0 0 0 结束。
输出格式
对于每组数据,输出形如 n = a + b
,其中 a , b a,b a,b 是奇素数。
若有多组满足条件的 a , b a,b a,b,输出 b − a b-a b−a 最大的一组。
若无解,输出 Goldbach's conjecture is wrong.
。
数据范围
输入最多包含 50006 50006 50006 组数据。
6 ≤ n < 1 0 6 6 \le n < 10^6 6≤n<106
输入样例:
8
20
42
0
输出样例:
8 = 3 + 5
20 = 3 + 17
42 = 5 + 37
思路
显然这是一道关于质数的题。
观察数据范围,我们发现,需要复杂度最高是 O ( n ) O(n) O(n) 的算法才能过。
所以我们考虑使用线性筛预处理出 1 ∼ 1 0 6 1 \sim 10^6 1∼106 的所有质数,然后从第一个开始枚举。
如果 p ∈ P p \in \mathbb{P} p∈P 且 n − p ∈ P n-p \in \mathbb{P} n−p∈P,则输出。( P \mathbb{P} P 为质数集)
最后我们考虑无解的情况。
虽然哥德巴赫猜想没有被证明,但是通过我们暴力算法的验证,我们发现在 1 0 6 10^6 106 的范围内的哥德巴赫猜想 一定有解。
所以即使你不考虑无解情况照样 AC \color{green}\text{AC} AC。
但是作者因为考虑到题解的严谨性,还是写了无解情况的判断。具体细节请看代码。
算法时间复杂度
AC Code
C + + \text{C}++ C++
#include <iostream>using namespace std;const int N = 1e6 + 10;int n;
int primes[N], cnt;
bool st[N];void get_primes() // 线性筛质数
{st[1] = true; // 这里特殊处理1不是质数(我们用false表示质数)for (int i = 2; i < N; i ++ ){if (!st[i]) primes[cnt ++ ] = i;for (int j = 0; primes[j] <= N / i; j ++ ){st[primes[j] * i] = true;if (i % primes[j] == 0) break;}}
}int main()
{get_primes(); // 处理 1 ~ 1e6 所有质数while (cin >> n && n){bool flag = 0;for (int i = 1; primes[i] <= n; i ++ )if (!st[n - primes[i]]) // 如果n-primes[i]是质数就输出{printf("%d = %d + %d\n", n, primes[i], n - primes[i]);flag = 1;break;}if (!flag) puts("Goldbach's conjecture is wrong."); // 无解情况}return 0;
}
最后,如果觉得对您有帮助的话,点个赞再走吧!