题意:给你一个n个元素的数组,给你一个sum,让你找到数组的子集使得子集元素和等于sum,保证只有一个解决方案。
n<=36, sum < 9e18
思路:爆搜肯定是不行的,有一个很巧妙的思路,就是将数组分成两个区域,18个元素我们完全可以暴力枚举子集,并放到set里,
然后再对右区域枚举子集,O(1)检查sum - 子集和是否存在就行了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll a[maxn];
set<ll> s;
map<ll, ll> mp;
int main()
{
int n, p, q;
ll sum;
scanf("%d %lld", &n, &sum);
p = n / 2; q = n - p;
for(int i = 0; i < n; ++i)
scanf("%lld", &a[i]);
for(int i = 0; i < (1 << p); ++i) //先枚举左区间
{
ll tmp = 0;
for(int j = 0; j < p; ++j)
{
if(i & (1 << j))
tmp += a[j];
}
s.insert(tmp);