求大于6的素数之和

题目

给你一个自然数N,求[6,N]之内的所有素数中,两两之和为偶数的那些偶数。

解题思路

哥德巴赫猜想:任何大于2的偶数都可以表示成两个素数的和。

单纯的因为哥德巴赫猜想直接打印那些偶数也是不对的,例如,某些偶数(比如22=11+11)不可以拆分为两个不同素数之和。若直接打印偶数也需要判断那些偶数是哪两个不同素数之和(判断一个这样的偶数至少是线性复杂度),不能包含3和5。因此考虑使用枚举方法(时间复杂度O(n^2)):

  1. 找出[6,N]之间的所有素数;

  2. 求这些素数两两之和;

  3. 对得到的素数之和排序、去重、打印。

源程序

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define N (20000)
#define M (N/2)

static int primes[M]; /*编译器初始化了0*/
static int sums[M*M]; /*任意两素数之和*/
int my_cmp (const void * a, const void * b);

/* 判断一个数是不是素数,是素数则返回它自己;否则返回0 */
int is_prime (int x){
    int i,t;
    int ans = 0;
    if (x<=1 || 0==x%2){
        return ans;
    }
    t = (int)sqrt (x);
    for (i=3;i<=t;i+=2){
        if (0 == x%i){
            return ans;
        }
    }
    return (ans = x);
}

/* 保存区间的素数到全局数组primes */
void primes_in (int low, int high){
    int i=0,j=low;
    while (j<=high){
        if (is_prime (j)){
            primes[i++]=j;
        }
        j++;
    }
}/*数组中的非零元素就是区间中的素数 */

/*求区间中素数的和并打印出来 */
void solve (int left, int right){
    int i,j,k;
    int t; /*记录素数的个数*/
    primes_in (left,right);
    for (t=0; t<M; t++){
        if (!primes[t]){
            break;
        }
    }
    for (k=0,i=0; i<t; i++){
        for (j=i; j<t; j++){
            sums[k++]=primes[i]+primes[j];   
        }
    }
    /*排序*/
    qsort (sums, k, sizeof (int), my_cmp); 
    /*去重*/
	i=0;
    for (j=i+1; j<k; j++){
        if (sums[j] > sums[i]){
            sums[++i] = sums[j];
        }
    }  
    /*打印*/
    for (j=0;j<=i;j++){
        printf ("%d, %d\n", j+1, sums[j]);
    }
}

int my_cmp (const void * a, const void * b){
    return (*(int *)a - *(int *)b);
}

/* 程序入口 */
int main (){
    solve (6,N);
    return 0;
}


你可能感兴趣的:(求大于6的素数之和)