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