# BZOJ2339: [HNOI2011]卡农(dp 容斥)

## 题意

• 集合不为空
• 任意两个集合不相同
• 集合内各个元素xor起来等于0

## Sol

f[i]=A_{2^n-1}^{i-1}-f[i-1]-(i-1)\times f[i-2]\times(2^n-1-(i-2))

// luogu-judger-enable-o2
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stack>
#include<vector>
#include<cstring>
#define LL long long
//#define int long long
using namespace std;
const int MAXN = 3 * 1e6;
const LL mod = 1e8 + 7;//fuck
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, M;
LL ifac[MAXN], fac[MAXN], f[MAXN], A[MAXN];
LL fastpow(LL a, LL p) {
LL base = 1;
while(p) {
if(p & 1) base = (base * a) % mod;
a = (a * a) % mod; p >>= 1;
}
return base % mod;
}
main() {
N = read(); M = read(); LL base = fastpow(2, N) % mod;
fac[0] = A[0] = 1; for(int i = 1; i <= M; i++) fac[i] = 1ll * i * fac[i - 1] % mod;
ifac[M] = fastpow(fac[M], mod - 2);
for(int i = 1; i <= M; i++) A[i] = 1ll * A[i - 1] * (base - i + mod) % mod;
f[0] = 1; f[1] = 0;
for(int i = 2; i <= M; i++) f[i] = ((A[i - 1] - f[i - 1] + mod) % mod - 1ll * f[i - 2] * (i - 1) % mod * (base - i + 1) % mod + mod) % mod;
printf("%lld", f[M] * ifac[M] % mod);
return 0;
}
/*
99999 99999
*/

posted @ 2018-08-27 10:47  自为风月马前卒  阅读(157)  评论(0编辑  收藏  举报