抽签问题
n个纸片放入口袋,抽四次,抽完放回去,如果和为m则你赢
1<=n<=50 1<=n<=10^8 1<=ki<=10^8
输入 n=3,m=10,k={1,3,5}
输出 Yes
这个一看也好写,就是四个循环嘛,相加看看是不是=m就行了,但是书上说还有一种方法,四个循环对于n较小还可以,n要是太大就不行了,所以就要找一个方法使循环少一个,就是把内层的循环换成m-k[a]-k[b]-k[c]来二分查找,如果找到就yes,找不到就no
#include<cstdio>
#include<algorithm>
using namespace std;//用sort就一定要加这个,因为打开域名std,sort在域名std下,表明这个sort是standard的sort()
int n,m,k[1000000];
bool binary_search(int x)//如果不把n什么的设为全局变量,则无法进行调用函数,这里面有n,k[i]什么的,还要写在调用函数里面,比较麻烦,不如全局
{
int l=0,r=n;
while(r-l>=1)
{
int i=(l+r)/2;
if(k[i]==x)
return true;
else if(k[i]<x)
l=i+1;
else
r=i-1;
}
return false;
}
int main()
{
int i;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
scanf("%d",&k[i]);
sort(k,k+n);//要用二分就必须要排好序
bool f=false;
for(int a=0;a<n;a++) {
for(int b=0;b<n;b++) {
for(int c=0;c<n;c++) {
if(binary_search(m-k[a]-k[b]-k[c]))//发现不好写的东西就试试调用
f=true; } } }
if(f) puts("Yes");//要用引号
else puts("No");
return 0;
}
还有一种是少两个循环,
#include<cstdio>
#include<algorithm>
using namespace std;
int m,n,k[100];
int kk[10000];
bool binary_search(int x)
{
int l=0,r=n*n;
while(r-l>=1)//这个是r-l>=一,是数字一,不是l,而且不能写r>=l,这样根本不输出
{
int i=(l+r)/2;
if(kk[i]==x)
return true;
else if(k[i]<x)
l=i+1;
else
r=i;
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&k[i]);
bool f=false;
for(int c=0;c<=n;c++)
{
for(int d=0;d<n;d++)
{
kk[c*n+d]=k[c]+k[d];//这里也可以写j=0;j++
}
}
sort(kk,kk+n*n);
for(int a=0;a<n;a++)
{
for(int b=0;b<n;b++)
{
if(binary_search(m-k[a]-k[b]))
f=true;
}
}
if(f)
puts("Yes");
else
puts("No");
return 0;
}
这个题看了半天都过不去,怎么改都没有输出,结果同学看了之后说我1和l分不清……