zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem——哈希表&&二进制枚举

    题意

    有长度为 $n$($1leq nleq 36$)的数列,给出 $s$,求和为 $s$ 的子集,保证子集存在且唯一。

    分析

    答案肯定是来自左右半边两部分组成的。

    如果我们用哈希表存一半,计算另一半的值 $v$,再在哈希表中查找 $s-v$,这样规模从 $2^{36}$ 降至 $2^{18}$,其实就是折半搜索。

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef  long long ll;
    ll n, s, a[40];
    ll A[1 << 20];
    unordered_map<ll, int>mp;
    
    int main()
    {
        scanf("%lld%lld", &n, &s);
        for(int i = 0;i < n;i++)  scanf("%lld", &a[i]);
    
        int l = n / 2;  //左边的长度
        for(int i = 0;i < (1 << l);i++)
            for(int j = 0;j < l;j++)
            {
                if((i >> j) & 1)
                    A[i] += a[j];
            }
    
        int r = n - l;  //右边的长度
        for(int i = 0;i < (1 << r);i++)
        {
            ll tmp = 0;
            for(int j = 0;j < r;j++)
            {
                if((i >> j) & 1)
                    tmp += a[j+l];
            }
            mp[tmp] = i;
        }
    
        //查找
        for(int i = 0;i < (1 << l);i++)
        {
            ll cha = s - A[i];
            if(mp.count(cha))
            {
                for(int j = 0;j < l;j++)
                {
                    if((i >> j) & 1)  printf("1");
                    else printf("0");
                }
                for(int j = 0;j < r;j++)
                {
                    if((mp[cha] >> j) & 1)  printf("1");
                    else  printf("0");
                }
                printf("
    ");
                break;
            }
        }
        return 0;
    }
  • 相关阅读:
    HDU 2955 Robberies
    HDU 2546 饭卡
    poj 3628 Bookshelf 2
    poj 3624 Charm Bracelet
    celery -1
    ☀【Grunt】插件
    【MooTools】
    【Grunt】
    ↗☻【PHP与MySQL程序设计 #BOOK#】第3章 PHP基础
    【CSS】
  • 原文地址:https://www.cnblogs.com/lfri/p/11360824.html
Copyright © 2011-2022 走看看