2019牛客暑期多校训练营(第九场) - D - Knapsack Cryptosystem(折半枚举)
作者:互联网
题目链接:https://ac.nowcoder.com/acm/contest/889/D
题意:挑选若干个数使得和为s。
思路:考虑二进制枚举,但是n的范围是36,直接枚举会超时,所以我们把数组分两部分枚举,然后用map映射一下即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll a[50], sum, s;
int m, n;
map <ll, string> mp1, mp2;
string str;
int main()
{
scanf("%d%lld",&n, &s);
for(int i = 0; i < n; i++) scanf("%lld", &a[i]);
m = n / 2; n = n - m;
for(int i = 0; i < (1 << m); i++)
{
sum = 0; str = "";
for(int j = 0; j < m; j++)
{
if(i & (1 << j))
sum += a[j], str += '1';
else str += '0';
}
mp1[sum] = str;
}
for(int i = 0; i < (1 << n); i++)
{
sum = 0; str = "";
for(int j = 0; j < n; j++)
{
if(i & (1 << j))
sum += a[m+j], str += '1';
else str += '0';
}
mp2[sum] = str;
}
for(auto it : mp1)
if(mp2.count(s-it.first))
return cout << it.second << mp2[s-it.first] << endl, 0;
}
标签:折半,map,int,scanf,Cryptosystem,多校,long,枚举,lld 来源: https://blog.csdn.net/sugarbliss/article/details/99683035