宣传一下 算法提高课整理
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;
}
最后,如果觉得对您有帮助的话,点个赞再走吧!