题目:每次从n个数里抽取一个数记录后并放回,问是否存在抽取的四个数之和为m的情况。
当n<10的时候,直接枚举即可;当n<1000时,则需要进行优化,先将四个数分为俩俩之和,再对结果进行二分搜索。
下面的算法时间复杂度为O(n^2 log n)。
#include <iostream>
#include<algorithm>
using namespace std;
int n,m;
int a[1005],b[1000005];
bool b_search(int x);
void solve();
int main()
{
while(cin>>n>>m){
for(int i=0;i<n;i++){
cin>>a[i];
}
solve();
}
return 0;
}
bool b_search(int x){
int l=0,r=n*n-1;
while(l<=r){
int mid=(r+l)/2;
if(b[mid]==x) return 1;
else if(b[mid]>x) r=mid-1;
else l=mid+1;
//debug
//cout<<mid<<":"<<b[mid]<<",";
}
return 0;
}
void solve(){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
b[i*n+j]=a[i]+a[j];
}
}
sort(b,b+n*n);
for(int i=0;i<n*n;i++){
//调用STL
/* if(binary_search(b,b+n*n,m-b[i])){
cout<<"yes\n";return;
}*/
if(b_search(m-b[i])){
cout<<"yes\n";return;
}
}
cout<<"no\n";
}