题解 | #查找组成一个偶数最接近的两个素数#
查找组成一个偶数最接近的两个素数
http://www.nowcoder.com/practice/f8538f9ae3f1484fb137789dec6eedb9
题意
给定多个偶数,找两个质数使得其和为该偶数,且这两个质数之差最小
限制,偶数在之间
方法
预处理
我们先计算出质数表,随后枚举质数对,计算它们的和,更新结果
以题目的20为例,考虑小于20的质数有,我们只考虑和为偶数的情况
以下展示了v2pair
20以内的变化情况
- | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 |
---|---|---|---|---|---|---|---|---|---|
初始化 | 0,0 | 0,0 | 0,0 | 0,0 | 0,0 | 0,0 | 0,0 | 0,0 | 0,0 |
i=2,j=2 | 2,2 | - | - | - | - | - | - | - | - |
i=3,j=3 | - | 3,3 | - | - | - | - | - | - | - |
i=3,j=5 | - | - | 3,5 | - | - | - | - | - | - |
i=3,j=7 | - | - | - | 3,7 | - | - | - | - | - |
i=3,j=11 | - | - | - | - | - | 3,11 | - | - | - |
i=3,j=13 | - | - | - | - | - | - | 3,13 | - | - |
i=3,j=17 | - | - | - | - | - | - | - | - | 3,17 |
i=5,j=5 | - | - | - | 5,5 | - | - | - | - | - |
i=5,j=7 | - | - | - | - | 5,7 | - | - | - | - |
i=5,j=11 | - | - | - | - | - | - | 5,11 | - | - |
i=5,j=13 | - | - | - | - | - | - | - | 5,13 | - |
i=7,j=7 | - | - | - | - | - | 7,7 | - | - | - |
i=7,j=11 | - | - | - | - | - | - | - | 7,11 | - |
i=7,j=13 | - | - | - | - | - | - | - | - | 7,13 |
那么对于20来说答案就是7和13了
代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i = (a);i<(b);i++)
vector<pair<int,int> > v2pair(1001,make_pair(0,0));
int main(){
vector<bool> p(1001,true); // 质数表
rep(i,2,1001){
if(!p[i])continue;
rep(j,i,1001){
if(i*j>1000)break;
p[i*j] = false;
}
}
rep(i,2,1001){ // 枚举小质数
if(!p[i])continue;
rep(j,i,1001){ // 枚举大质数
if(!p[j])continue;
if(i+j > 1000)break; // 控制和的范围
// {0,0} 或 差值更大
if(v2pair[i+j].first + v2pair[i+j].second != i+j || v2pair[i+j].second - v2pair[i+j].first > j-i){
v2pair[i+j] = {i,j}; // 更新最小差的两个质数
}
}
}
int n;
while(~scanf("%d",&n)){
printf("%d\n%d\n",v2pair[n].first,v2pair[n].second);
}
return 0;
}
复杂度分析
设有m个查询
时间复杂度: 初始化质数表,枚举所有质数对的时间复杂度为,对于每个查询,所以总时间复杂度为
空间复杂度: 两部分,一个是质数表储存,一个是预处理的结果储存,两部分都是,所以总时间复杂度为
每次搜索
我们同样预先计算出质数表,但是我们不计算结果,每次查询时再去搜"质数"和"当前偶数减去一个质数"
代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i = (a);i<(b);i++)
int main(){
vector<bool> p(1001,true); // 质数表
rep(i,2,1001){
if(!p[i])continue;
rep(j,i,1001){
if(i*j>1000)break;
p[i*j] = false;
}
}
int n;
while(~scanf("%d",&n)){
pair<int,int> ans={0,n}; // 初始化和
rep(i,2,1001){
if(!p[i])continue; // i 是质数
int j = n-i; // 当前偶数减去一个质数
if(j < i)break; // j>=i
if(!p[j])continue; // j 是质数
ans={i,j};
}
printf("%d\n%d\n",ans.first,ans.second);
}
return 0;
}
复杂度分析
时间复杂度: 初始化质数表, 对于每个查询最坏代价是,所以总时间复杂度为
空间复杂度: 我们额外空间主要是质数表,其余空间都是常数大小,所以总空间复杂度为