数学领域著名的“哥德巴赫猜想”的大致意思是:任何一个大于2的偶数总能表示为两个素数之和。比如:24=5+19
,其中5
和19
都是素数。本实验的任务是设计一个程序,验证20亿
以内的偶数都可以分解成两个素数之和。
输入格式:
输入在一行中给出一个(2, 2 000 000 000]
范围内的偶数N
。
输出格式:
在一行中按照格式“N = p + q
”输出N
的素数分解,其中p ≤ q
均为素数。又因为这样的分解不唯一(例如24还可以分解为7+17
),要求必须输出所有解中p
最小的解。
输入样例:
24
输出样例:
24 = 5 + 19
代码:
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
typedef long long int long_int;
int judge_is_prime(int x){
int isPrime = 1,i = 3;
if(x == 1 || x % 2 == 0 && x != 2) isPrime = 0;
else {
for(;i<=sqrt(x);i+=2){
if(x % i == 0){
isPrime = 0;
break;
}
}
}
return isPrime;
}
int main() {
long_int N,p,q;
scanf("%lld",&N);
// 现在需要编写一个函数判断数是否是素数
for (p=2;p<=N/2;p++) {
// p是较小的一方
q = N - p;
// 成功从n**2级别降低到n层面
if (judge_is_prime(p) && judge_is_prime(q)) {
printf("%lld = %lld + %lld\n",N,p,q);
break;
}
}
return 0;
}
提交截图:
解题思路:
这道题让我清楚的认识到了算法的重要性!下面是解决这道题时遇到的一些问题:
① 下面是最开始编写的代码,时间复杂度大约 O ( n 2 ) O(n^{2}) O(n2)
# include <stdio.h>
# include <stdlib.h>
typedef long long int long_int;
int judge_is_prime(int a) {
int i,value = 1;
if (a == 2) {
value = 1;
}else {
for (i=2;i<a;i++) {
if (a % i == 0) {
// 能被[2,i)因子整除则不是素数
value = 0;
}
}
}
return value;
}
int main() {
long_int N,p,q;
scanf("%lld",&N);
// 现在需要编写一个函数判断数是否是素数
for (p=2;p<N;p++) {
for (q=N-1;q>=2;q--) {
if (judge_is_prime(p) && judge_is_prime(q) && p + q == N) {
goto sum;
}
}
}
sum:printf("%d = %d + %d\n",N,p,q);
return 0;
}
直接报错:在这里插入图片描述
② 后来对算法改进,发现第二层循环不需要,因为p +q == N
,于是算法成为O(n)
层级!
③ 发现还是有问题,将goto
语句去除还是不行,于是意识到是函数编写的问题,于是将判断素数的循环范围从i < n
变成i < sqrt(n)
,这样发现第四个案例又出问题了,于是再次修改函数的判断条件,改为从3开始,逐次加2……终于通过了!难顶