题目的主要信息:
- 任意一个大于2的偶数都可以由2个素数组成,组成偶数的2个素数有很多种情况
- 求组成指定偶数的两个素数差值最小的素数对
- 一定输出大于2的偶数,最大不超过1000
方法一:穷举
具体做法:
对于一个数字,我们可以从2遍历到n,寻找两个加数都是素数的情况,然后比较素数之间的差值,把要输出的变量更新为更小的差值及这两个变量,最后枚举完得到就是差值最小的两个素数。
检查一个数是否是素数,我们也可以穷举法,从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(1),无额外空间
方法二:穷举优化
具体做法:
首先我们可以肯定两个加数越靠近差值就越小,而就是我们要的值,我们也直到越靠近的n/2的两个加数差值越小,因此我们可以从n/2开始,找到第一对都是素数的加数,直接输出即可,因为一定存在,因此不用遍历完整个数组。
检查一个数是否是素数时,我们也可以只检查到√n,因为大于√n的因子势必要与一个小于√n的因子相乘,而小于等于√n的因子检查完之后,就不会有大于√n的因子。
#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(n∗√n),外循环最多遍历n/2次,内循环每个数最多是O(√n)
- 空间复杂度:O(1),无额外空间