#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 22; // 左边分1的数量 -> a, 分2的 -> b,右分1 -> c, 分2 -> d
// 只要满足 a + c == b + d 就行
ll n, half, a[N], S, ans, cnt[1 << N], tot;
vector < ll > G[1 << N];
unordered_map < ll, int > M;
void dfs(int x, int sum, int state) { // 枚举所有a - b
if(x == half + 1) {
if(!M[sum]) M[sum] = ++tot;
// 当state是空集时,正好可以统计只选右边的情况
G[M[sum]].push_back(state);
return;
}
dfs(x + 1, sum + a[x], state | (1 << x - 1)); // 放左边
dfs(x + 1, sum - a[x], state | (1 << x - 1)); // 放右边
dfs(x + 1, sum, state); // 不放
}
void DFS(int x, int sum, int state) { // 枚举所有d - c
if(x > n) {
if(!M[sum]) return;
int t = M[sum];
for(int i = 0; i < G[t].size(); i++) cnt[state | G[t][i]] = true;
// 当state是空集时,正好可以统计只有左边的情况
return;
}
DFS(x + 1, sum + a[x], state | (1 << x - 1)); // 放右边
DFS(x + 1, sum - a[x], state | (1 << x - 1)); // 放左边
DFS(x + 1, sum, state); // 不放
}
int main() {
cin >> n; half = n >> 1;
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
dfs(1, 0, 0);
DFS(half + 1, 0, 0);
for(int i = 1; i < (1 << n); i++) ans += cnt[i]; // 从1开始是为了避免空集
printf("%lld\n", ans);
return 0;
}
P3067 [USACO12OPEN] Balanced Cow Subsets G题解
最新推荐文章于 2024-10-16 00:00:43 发布