传送门
可以发现,
(
n
m
)
≡
1
(
m
o
d
2
)
\binom{n}{m}\equiv 1(mod~2)
(mn)≡1(mod 2) 当且仅当
m
a
n
d
n
=
m
m~and~n~=~m
m and n = m
即
m
m
m 二进制下为
n
n
n 的子集
那么可以直接写一个
3
18
3^{18}
318 的枚举子集
D
P
DP
DP
但是还有一个
6
9
6^9
69 的做法
把数字分成前
9
9
9 位和后
9
9
9 位
设
f
(
s
1
,
s
2
)
f(s_1,s_2)
f(s1,s2) 表示前
9
9
9 位为
s
1
s_1
s1,后
9
9
9 位为
s
2
s_2
s2 的超集的答案
那么对于一个数
x
x
x,分成
x
1
,
x
2
x_1,x_2
x1,x2,转移的时候枚举
x
1
x_1
x1 的超集,更新的时候枚举
x
2
x_2
x2 的子集即可
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn(1 << 9);
const int mod(1e9 + 7);
inline void Inc(int &x, int y) {
x = x + y >= mod ? x + y - mod : x + y;
}
int n, f[maxn][maxn], sz = maxn - 1;
int main() {
register int i, j, v, f1, f2, t, g;
scanf("%d", &n);
for (i = 1; i <= n; ++i) {
scanf("%d", &v), f1 = v >> 9, f2 = v & sz, g = 1;
for (t = j = sz ^ f1; ; j = (j - 1) & t) {
Inc(g, f[sz ^ j][f2]);
if (!j) break;
}
for (j = f2; ; j = (j - 1) & f2) {
Inc(f[f1][j], g);
if (!j) break;
}
}
for (g = mod - n, i = 0; i <= sz; ++i) Inc(g, f[i][0]);
printf("%d\n", g);
return 0;
}