Knapsack Cryptosystem 牛客团队赛

时限2s
题意:

第一行包含两个整数,分别是n(1 <= n <= 36)和s(0 <= s <9 * 10 18
第二行包含n个整数,它们是{a i }(0 <a i <2 * 10 17)。
 {ai}就像在Merkle–Hellman背包密码系统中一样生成,因此存在一个解决方案,并且该解决方案是唯一的。
如果数组{ai}是需要的输出1,不需要的输出0
样例:
输入

8 1129
295 592 301 14 28 353 120 236

输出

01100001

思路:

因为n是36,2^36明显会超时,所以用折半枚举;

用两个map一个存前半段2^(n/2)的不同和以及输出状态

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define modd 998244353
const int maxn=4e4+10;
ll kk,a[43];
int n;
map<ll,int>m;
map<ll,string>mp;
int main(){
    scanf("%d%lld",&n,&kk);
    for (it i = 0; i < n; i++){
        scanf("%lld", &a[i]);
    }
    for (it i = 0; i < 1 << (n / 2); i++){
        ll sum = 0;
        string c = "";
        for (it j = 0; j < n / 2; j++){
            if ((i >> j) & 1){
                sum += a[j];
                c+= "1";
            }
            else{
                c += "0";
            }
        }
        m[sum]++;
        mp[sum] = c;
    }
    int wk=n - n / 2;
    for (it i = 0; i < 1 << wk; i++){
        ll sum = 0;
        string c = "";
        for (it j = 0; j < wk; j++){
            if ((i >> j) & 1) {
                sum += a[j + n / 2];
                c += "1";
            }
            else{
                c += "0";
            }
        }
        if(m[kk - sum]==1){
            cout << mp[kk - sum] << c << endl;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/luoyugongxi/p/12347551.html