- 哥德巴赫猜想了啥?
所谓猜想,通常指的是基于现有知识或观察做出的未经证实的推测或推断。在数学领域,猜想是指那些被提出但尚未经过严格证明的命题,它们可能是正确的,也可能是错误的,也可能仍然在验证的过程中。
克里斯蒂安.哥德巴赫曾经猜想,每个奇合数可以写成一个素数和一个平方的两倍之和。
例如:
9 = 7 + 2 x
15 = 7 + 2 x
21 = 3 + 2 x
25 = 7 + 2 x
27 = 19 + 2 x
33 = 31 + 2 x
... ....
这个猜想最终被推翻了,那么问题来了,不能写成一个素数和一个平方的两倍之和的最小奇合数是多少?
- 题目分析
题目要求找到不符合猜想的反例,我们通常的正向思维逻辑就是枚举找到不满足约束条件的第一个值,那么约束条件是什么呢?
第一:研究对象是奇数,且是合数;
第二:它要写成一个素数和一个平方的两倍。
即枚举找到第一个是奇合数,但不满足上述条件的值。
分析到这里,我们发现这又是一道涉及到素数的问题,经过之前几篇文章的总结,我们会立刻想到素筛法或线性筛法, 那么这道题目可以套用素筛法或线筛法的框架吗?可以!
解题思路:
1. 研究对象是合数,所以先把素数排除在外;
2. 将所有的偶数排除;
3. 利用线性筛算法,找到数据范围内的所有素数;
4. 模拟素数筛的标记过程,使用素数去标记掉范围内所有满足条件的数字;
重点来了,之前我们学习的素数筛是用当前遍历到的素数值去标记它的所有倍数值,因为素数值的倍数肯定是一个合数,这样我们就可以把数据范围内的所有合数都做了标记,但是对于这道题,标记条件就要根据题意做出修改:
例如,当前遍历到的素数是7, 我们标记的就是7 加上 1到N 区间内的所有值的平方的2倍,
7 + 2 x
7 + 2 x
7 + 2 x
... ....
7 + 2 x
5. 遍历标记后的数据结构,第一个未被标记的值,就是一个奇合数。
- 代码实现
#include <stdio.h>
#define MAX_N 1000000
int prime[MAX_N+5] = {0};// 存储所有素数
int arr[MAX_N+5] = {0}; // 记录最终标记结果
//利用线性筛算法得到所有素数
void init_prime(){
for(int i = 2; i <= MAX_N;i++){
if(!prime[i]){
prime[++prime[0]] = i; // 存储所有素数
arr[i] = 1; // 将素数的位置标记为1,即将素数排除
}
for(int j = 1; j <= prime[0]; j++){
if(i * prime[j] > MAX_N) break;
prime[prime[j] *i] = 1;
if(i % prime[j] == 0) break;
}
}
return;
}
int main(){
init_prime();
//利用素数筛的标记思想,标记所有符合条件的数
for(int i = 1; i <= prime[0]; i++){
for(int n = 1;;n++){
if(prime[i] + 2 *n*n > MAX_N) break;
arr[prime[i]+2*n*n] = 1; // 将满足条件:N= 素数+ 2*n*n 的数标记为1;
}
}
//此时的arr中,素数都被标记为1,满足条件:素数+ 2*n*n 的数也被标记为了1;
//此时的arr中,未被标记的数据应该都是合数;
for(int i = 9; i<= MAX_N; i+=2){ //从第一个奇合数开始遍历,
if(arr[i]) continue;
printf("%d\n", i); //找的了第一个不满足条件的奇合数!
break;
}
return 0;
}
运行结果:
Tip:
「哥德巴赫猜想:
哥德巴赫猜想是数学中的一个未解决问题,由德国数学家克里斯蒂安·哥德巴赫于1742年提出。原始的猜想是:任一大于2的偶数都可以表示为两个素数之和。由于现代数学不再将1视为素数,哥德巴赫猜想的现代表述为:任一大于5的整数都可以表示为三个素数之和。此外,还有一个等价的版本,即任一大于2的偶数都可以表示为两个素数之和,这通常被称为“强哥德巴赫猜想”或“关于偶数的哥德巴赫猜想”
哥德巴赫猜想自提出以来,吸引了无数数学家的研究。1966年,中国数学家陈景润证明了“1+2”成立,即“任一充分大的偶数都可以表示成二个素数的和,或是一个素数和一个半素数的和”。2013年5月,巴黎高等师范学院研究员哈洛德·贺欧夫各特宣布彻底证明了弱哥德巴赫猜想,即任一大于5的奇数都可以表示为三个素数之和。尽管这些进展非常重要,但哥德巴赫猜想的完整证明尚未完成。」