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; }