题目的主要信息:

  • 任意一个大于2的偶数都可以由2个素数组成,组成偶数的2个素数有很多种情况
  • 求组成指定偶数的两个素数差值最小的素数对
  • 一定输出大于2的偶数,最大不超过1000

方法一:穷举

具体做法:

对于一个数字,我们可以从2遍历到n,寻找两个加数都是素数的情况,然后比较素数之间的差值,把要输出的变量更新为更小的差值及这两个变量,最后枚举完得到就是差值最小的两个素数。

alt

检查一个数是否是素数,我们也可以穷举法,从2遍历到n,查看这个数是否由因子,如果有因子就一定不是素数,否则遍历完了还没有因子就是素数。

#include<iostream>
using namespace std;

bool isPrime(int n){ //判断数字n是否是素数
    for(int i = 2; i < n; i++){ //遍历到n-1
        if(n % i == 0) //如果由因子就不是素数
            return false;
    }
    return true; //遍历完都没有就是素数
}

int main(){
    int n;
    while(cin >> n){
        int mindis = n;
        pair<int, int> res; //记录两个素数
        for(int i = 2; i < n; i++){ //遍历2到n找到两个素数
            if(isPrime(i) && isPrime(n - i)){ //两个数都是素数的时候
                if(abs(n - i - i) < mindis){ //找距离最小
                    res = {i, n - i}; //更新最小
                    mindis = abs(n - i - i);
                }
            }
        }
        cout << res.first << endl << res.second << endl;
    } 
    return 0;
}

复杂度分析:

  • 时间复杂度:O(n2)O(n^2)O(n2),最坏情况第一次枚举一层循环,检查是否是素数一层循环
  • 空间复杂度:O(1)O(1)O(1),无额外空间

方法二:穷举优化

具体做法:

首先我们可以肯定两个加数越靠近差值就越小,而就是我们要的值,我们也直到越靠近的n/2n/2n/2的两个加数差值越小,因此我们可以从n/2n/2n/2开始,找到第一对都是素数的加数,直接输出即可,因为一定存在,因此不用遍历完整个数组。

检查一个数是否是素数时,我们也可以只检查到√n,因为大于√n的因子势必要与一个小于√n的因子相乘,而小于等于√n的因子检查完之后,就不会有大于√n的因子。

alt

#include<iostream>
#include<math.h>
using namespace std;

bool isPrime(int n){ //判断数字n是否是素数
    for(int i = 2; i * i <= n; i++){ //遍历到根号n
        if(n % i == 0)
            return false;
    }
    return true;
}

int main(){
    int n;
    while(cin >> n){
        int mindis = n;
        pair<int, int> res; //记录两个素数
        for(int i = n / 2; i > 1; i--){ //从n的中间开始找
            if(isPrime(i) && isPrime(n - i)){ //第一次遇见两个数都是素数的时候距离从小
                cout << i << endl << n - i << endl;
                break;
            }
        }
    } 
    return 0;
}

复杂度分析:

  • 时间复杂度:O(nn)O(n* √n)O(nn),外循环最多遍历n/2n/2n/2次,内循环每个数最多是O(n)O( √n)O(n)
  • 空间复杂度:O(1)O(1)O(1),无额外空间