抽签
试题描述
|
你的朋友提议玩一个游戏:将写有数字的n 个纸片放入口袋中,你可以从口袋中抽取4 次纸片,每次记下纸片上的数字后都将其放回口袋中。如果这4 个数字的和是m,就是你赢,否则就是你的朋友赢。你挑战了好几回,结果一次也没赢过,于是怒而撕破口袋,取出所有纸片,检查自己是否真的有赢的可能性。请你编写一个程序,判断当纸片上所写的数字是k1,k2, …, kn 时,是否存在抽取4 次和为m 的方案。 |
输入
|
第一行为两个整数n,m;第二行为n个整数k1,k2, …, kn 。
|
输出
|
如果存在,输出“Yes”;否则,输出“No”。
|
输入示例
|
3 10
1 3 5 |
输出示例
|
Yes
|
其他说明
|
1 ≤ n ≤ 50
1 ≤ m ≤ 10^8 1 ≤ ki ≤ 10^8 |
这道题最简单的做法就是:四个循环。但是这种情况下的时间复杂度太高了,所以需要优化。我用的是三个循环里面套二分,这样速度会由O(n^4)变为O(n^3logn),快了许多。
1 #include <iostream> 2 3 using namespace std; 4 int a[100]; 5 int x,n,m; 6 bool solve(int mid) //二分查找 7 { 8 int L=1,R=n; 9 10 while(R-L>=1) 11 { 12 mid=(L+R)/2; 13 if(a[mid]==x) return true; 14 else if(a[mid]<x) L=mid+1; 15 else R=mid; 16 } 17 return false; 18 } 19 20 int main() 21 { 22 bool hh=false; 23 scanf("%d%d",&n,&m); 24 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 25 sort(a+1,a+n); 26 for(int i=1;i<=n;i++) //三重循环 27 { 28 for(int j=1;j<=n;j++) 29 { 30 for(int k=1;k<=n;k++) 31 { 32 x=m-a[i]-a[j]-a[k]; 33 if(solve(x)) {printf("Yes");hh=true;break;} 34 } 35 if(hh==true) break; 36 } 37 if(hh==true) break; 38 } 39 if(hh==false) printf("No"); 40 //system("pause"); 41 return 0; 42 }