挑战程序设计竞赛 轻松热身 抽签问题-二分搜索(O(logn))

版权声明:《学习技巧》每次使用单边大脑的时间不要太久,连续使用左边大脑30分钟就如同连续使用左臂30分钟一样,周期性的交换让大脑两侧能够轮流休息,左脑活动包括了循序渐进的工作,解决逻辑问题与分析,而右脑活动包括了隐喻,创造性思考,模式匹配和可视化。 https://blog.csdn.net/intmainhhh/article/details/82556572

你的朋友提议玩一个游戏:将写有数字的n个纸片放入口袋中,你可以从口袋中抽取4次纸片,每次记下纸片上的数字后都将其放回口袋中。如果这4个数字的和是m,就是你赢,否则就是你的朋友赢。

请你编写一个程序,判断当纸片上所写的数字是k1,k2,... ,kn时,是否存在抽取4次和为m的方案。如果存在,输出为Yes;否则,输出为No。

限制条件:

1<=n<=1000

1<=m<=10^8

1<=ki<=10^8

样例输入

3 10

1 3 5

第一行代表n,m,第二行代表ki

样例输出:

扫描二维码关注公众号,回复: 3119180 查看本文章

Yes

例如当4次抽取的结果是1,1,3,5,和就是10

算法知识:

在C++的STL里面有lower_bound()和upper_bound()两个二分搜索的函数,

如在a[maxn]中搜索出现x的最小下标;就可以直接lower_bound(a,a+maxn,x);

如在a[maxn]中搜索出现x的最大下标;就可以直接upper_bound(a,a+maxn,x);

重要的时二分思想

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3;
int k[maxn],n,m,kk[maxn*maxn];
bool binary_search(int x) {
    int l=0;
    int r=n*n;
    while(l<r) {
        int index=l+(r-l)/2;
        if(kk[index]==x) return true;
        else if(k[index]<x) l=index+1;
        else r=index;
    }
    return false;

}
void solve() {
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
            kk[i*n+j]=k[i]+k[j];
    sort(kk,kk+n*n);
    bool flag=false;
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++) {
            if(binary_search(m-k[i]-k[j]))
                flag=true;
        }
    if(flag) puts("Yes");
    else puts("No");
}
int main() {
    cin>>n>>m;
    for(int i=0; i<n; i++) {
        cin>>k[i];
    }
    solve();

    return 0;
}

猜你喜欢

转载自blog.csdn.net/intmainhhh/article/details/82556572