原题链接:HDU5119
背包 DP
$f[i][j]$ 表示从前 $i$ 个中选,异或和恰好为 $j$ 的方案数。然后转移就看第 $i-1$ 个选还是没选。最后用滚动数组优化一下空间。
但是还是踩坑了,一直 RE,这里循环异或和的上界得是1 << 20
才行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| #include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int N = 42, M = 1 << 20;
int n, m, T, Case;
int a[N];
LL f[2][M]; // f[i][j]表示从前i个种选,异或和恰好为j的方案数
void solve() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
memset(f, 0, sizeof f);
f[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < M; j++) {
f[i & 1][j] = f[i - 1 & 1][j] + f[i - 1 & 1][j ^ a[i]];
}
}
LL res = 0;
for(int i = m; i < M; i++) res += f[n & 1][i];
printf("Case #%d: %lld\n", ++Case, res);
}
int main() {
cin >> T;
while (T--) solve();
return 0;
}
|