user-0 提问: 求哥德巴赫猜想

回复:
user: user-1
content: #include <stdio.h>  int isPrimeNumber(int n){     if(n<2) return 0;     if(n==2) return 1;     for(int i=2;i<n;i++){         if(n%i==0) return 0;     }     return 1;  } int main(void) {     int num;     printf("input a Even number (2 <number < 2000):");     scanf("%d",&num);     for(int i=2;i<num;i++){         if(isPrimeNumber(i)&& isPrimeNumber(num-i)){             printf("Even number %d = %d + %d\n",num,i,num-i);             break;         }     }     return 0; }

user: user-2
content: 引用 5 楼 user-3 的回复:应该先素数打表 然后用表里面的素数 两两现加  然后判断相加结果是不是把2000以内的全部偶数都沾满 这个想法不错，不用频繁去判断是否是素数 int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int pn[2000] = {0}; //用来保存素数     int pp[2000] = {0}; //用来快速定位素数     int i, j, flg=0, cnt=1; //素数个数     pn[0]=2;     pp[2]++;          for (i=3; i<2000; i+=2) { //找2000以内的素数         if (isPNum(i)) {             pn[cnt++] = i;             pp[i]++;         }     }          for (i=4; i<2000; i+=2) {         for (j=0; j<cnt; j++) {             if (pp[i-pn[j]] > 0) { //pn[j]是素数，i-pn[j]如果也是素数，则说明能分解                 printf("%d可以分解为%d+%d\n", i, pn[j], i-pn[j]);                 break;             }         }         if (j==cnt) { //j走到cnt说明i不能分解             flg++; //累加不能分解的个数         }     }     printf("2000以内大于2的偶数能否分解为2个素数之和？\n答案是：%s\n", flg?"No":"Yes"); //不能分解的个数大于0则说明答案是No，否则就是Yes }

user: user-3
content: 应该先素数打表 然后用表里面的素数 两两现加  然后判断相加结果是不是把2000以内的全部偶数都沾满

user: user-3
content: 引用 2 楼 qybao 的回复:for example int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int i, j, k;     for (i=4; i<=2000; i+=2) { //i是从4到2000的偶数         k = i>>1; //k=i/2是一个意思（取i的一半作为循环结束条件）         for (j=2; j<=k; j++) { //j和i-j是分解的两个数             if (j != i-j) {                 if (isPNum(j) && isPNum(i-j)) {                     printf("%d可以分解为%d+%d\n", i, j, i-j);                     break; //如果需要找出全部分解结果把这行注释掉                 }             } else {                 if (isPNum(j)) {                     printf("%d可以分解为%d+%d\n", i, j, j);                     break; //如果需要找出全部分解结果把这行注释掉                 }             }         }     }     return 0; } 其实这里素数会重复使用 那么打表显然是一个性价比更高的做法

user: user-3
content: 引用 1 楼 5250 的回复:最简单的双重循环 循环一下不就出来了嘛所以楼主最后说要尽量优化嘛

user: user-2
content: for example int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int i, j, k;     for (i=4; i<=2000; i+=2) { //i是从4到2000的偶数         k = i>>1; //k=i/2是一个意思（取i的一半作为循环结束条件）         for (j=2; j<=k; j++) { //j和i-j是分解的两个数             if (j != i-j) {                 if (isPNum(j) && isPNum(i-j)) {                     printf("%d可以分解为%d+%d\n", i, j, i-j);                     break; //如果需要找出全部分解结果把这行注释掉                 }             } else {                 if (isPNum(j)) {                     printf("%d可以分解为%d+%d\n", i, j, j);                     break; //如果需要找出全部分解结果把这行注释掉                 }             }         }     }     return 0; }

user: user-1
content: 最简单的双重循环 循环一下不就出来了嘛

user: user-3
content: #include <stdio.h> #include <string.h> #include <stdbool.h>  int initPrime(int* prime, int end) { 	bool arr[end]; 	memset(arr, 0, sizeof arr); 	for(int i=2; i<end; ++i) 		for(int j=i+i; j<end; j+=i) 			arr[j] = true;  	int count = 0; 	for(int i=2; i<end; ++i) 		if(!arr[i]) 			prime[count++] = i;  	return count; }  bool run(int* prime, int count, int end) { 	// 记录素数相加结果 出现4 则arr[4]为true 否则为false  	bool arr[end]; 	memset(arr, 0, sizeof arr); 	// 记录和为偶数的结果个数  	int res = 0; 	for(int i=0; i<count; ++i) 	{ 		for(int j=i; j<count && prime[i]+prime[j]<end; ++j) 		{ 			int tmp = prime[i] + prime[j];  			// 结果为偶数并且之前没有出现过 ++res  			if( !arr[tmp] &&  tmp%2==0 ) 				++res; 			arr[tmp] = true; 		} 	} 	// (end-1)/2 计算小于end的正偶数 因为要排除2 所以再减去1  	return res == (end-1)/2-1; }  int main(int argc, char *argv[]) { 	unsigned int n = 2000; 	//scanf("%u", &n); 	++n;  	int prime[n]; 	int count = initPrime(prime, n); 	if(run(prime, count, n)) 		puts("验证成功"); 	else 		puts("验证失败");  	return 0; }

user: user-2
content: 引用 9 楼 user-3 的回复：[quote=引用 6 楼 qybao的回复:][quote=引用 5 楼 user-3 的回复:]应该先素数打表 然后用表里面的素数 两两现加  然后判断相加结果是不是把2000以内的全部偶数都沾满 这个想法不错，不用频繁去判断是否是素数 int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int pn[2000] = {0}; //用来保存素数     int pp[2000] = {0}; //用来快速定位素数     int i, j, flg=0, cnt=1; //素数个数     pn[0]=2;     pp[2]++;          for (i=3; i<2000; i+=2) { //找2000以内的素数         if (isPNum(i)) {             pn[cnt++] = i;             pp[i]++;         }     }          for (i=4; i<2000; i+=2) {         for (j=0; j<cnt; j++) {             if (pp[i-pn[j]] > 0) { //pn[j]是素数，i-pn[j]如果也是素数，则说明能分解                 printf("%d可以分解为%d+%d\n", i, pn[j], i-pn[j]);                 break;             }         }         if (j==cnt) { //j走到cnt说明i不能分解             flg++; //累加不能分解的个数         }     }     printf("2000以内大于2的偶数能否分解为2个素数之和？\n答案是：%s\n", flg?"No":"Yes"); //不能分解的个数大于0则说明答案是No，否则就是Yes }[/quote] 把所有素数两两想加就可以了 不用判断每一个偶数能不能拆分[/quote]不光是两两相加，还要和自己相加，而且还要判断相加的和是否出现过，感觉不如分解方便。因为分解直接利用素数表，很容易就找到分解结果。

user: user-3
content: 引用 6 楼 qybao的回复:[quote=引用 5 楼 user-3 的回复:]应该先素数打表 然后用表里面的素数 两两现加  然后判断相加结果是不是把2000以内的全部偶数都沾满 这个想法不错，不用频繁去判断是否是素数 int isPNum(int num) { //判断是否是素数     if (num==2) return 1;     else if (num<2 || num%2==0) return 0;     int n = num>>1; //去num的一半作为循环结束条件     for (int i=3; i<=n; i+=2) {        if (num%i==0) return 0;     }     return 1; }  int main() {     int pn[2000] = {0}; //用来保存素数     int pp[2000] = {0}; //用来快速定位素数     int i, j, flg=0, cnt=1; //素数个数     pn[0]=2;     pp[2]++;          for (i=3; i<2000; i+=2) { //找2000以内的素数         if (isPNum(i)) {             pn[cnt++] = i;             pp[i]++;         }     }          for (i=4; i<2000; i+=2) {         for (j=0; j<cnt; j++) {             if (pp[i-pn[j]] > 0) { //pn[j]是素数，i-pn[j]如果也是素数，则说明能分解                 printf("%d可以分解为%d+%d\n", i, pn[j], i-pn[j]);                 break;             }         }         if (j==cnt) { //j走到cnt说明i不能分解             flg++; //累加不能分解的个数         }     }     printf("2000以内大于2的偶数能否分解为2个素数之和？\n答案是：%s\n", flg?"No":"Yes"); //不能分解的个数大于0则说明答案是No，否则就是Yes }[/quote] 把所有素数两两想加就可以了 不用判断每一个偶数能不能拆分