难度增加的抽签问题

                                                    抽签   

        将写有数字的N个纸片放入口袋中,你可以从口袋中抽取4次纸片,每次记下纸片的数字后都将其放回口袋中。编写一个程序,判断当纸片上所写的数字是k1, k2, ..., kn时,是否存在抽取4次和为m的方案。如果存在,输出Yes;否则, 输出No。

 

在数据较小的情况下(ex:50),我们可以直接利用四重循环解决问题,50的4次方才1e6,完全莫得问题。但数据一大就不行了。比如n取1000,1000的4次方就1e12了,电脑说我不干了你找别脑吧/笑哭。此时我们就要优化算法了。

这里我们利用了强大的二分法,直接可以降到n2logn级别,换句话说,当n=1000时,复杂度才1e7,简直不要太精彩!

下面是具体代码:

其实就是把内层的两个循环用二分法转化为logn级别了,另外注意数组的大小。

//输入
int n, m, k[MAXN];

//保存2个数的和的数列
int kk[MAXN * MAXN];

bool binary_search(int x)
{
    //x的存在范围是kk[l], kk[l+1], ..., kk[r-1]
    int l = 0, r = n * n;

    //反复操作直到存在范围为空
    while(r - l >= 1)
    {
        int i = (l + r) / 2;
        if(kk[i] == x) return true; //找到x
        else r = i;
    }

    //没找到x
    return false;
}

void solve()
{
    //枚举k[c] + k[d]的和
    for(int c = 0; c < n; c++)
    {
        for(int d = 0; d < n; d++)
        {
            kk[c * n + d] = k[c] + k[d];
        }
    }

    //排序以便进行二分搜索
    sort(kk, kk + n * n);

    bool f = false;
    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");

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值