0%

ARC093F Dark Horse

ARC093F

考虑11放哪都成,不如钦定在一号点,最后答案乘2n2^n即可

剩下的需要保证区间[2k1+1,2k][2^{k-1}+1,2^k]内的最小数字都不是AiA_i中的数字

都不是是个很麻烦的限制,考虑反演设fif_i是恰好有ii个区间AA中的元素是最小值,gig_i是至少有ii个区间是

易见gi=j=in(ji)fjfi=j=in(1)ji(ij)gig_i=\sum\limits_{j=i}^n\binom{j}{i}f_j \Leftrightarrow f_i=\sum\limits_{j=i}^n(-1)^{j-i}\binom{i}{j}g_i

gig_i可以状压 dp,具体来说,设dpi,jdp_{i,j}表示现在考虑到AiA_i并且区间的状态为jj的情况,其中jj每一位二进制的11代表第kk个区间填完了

因为要把一个AiA_i放在某一个区间中并且保证他最小,需要加入2k12^k-1个比他大的元素,从大到小排序,以防填数的时候把大的AiA_i填进去了

如果当前的AiA_i不作为最小值,那么dpi,j=dpi,j+dpi1,jdp_{i,j}=dp_{i,j}+dp_{i-1,j}

否则作为区间kk的最小值,那么dpi,j2k=dpi,j2k+dpi1,j×(2k12njAi)dp_{i,j|2^k}=dp_{i,j|2^k}+dp_{i-1,j}\times \binom{2^k-1}{2^n-j-A_i}

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int LIM = 21;
const ll mod = 1e9 + 7;
ll qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) {
res = res * a % mod;
}
a = a * a % mod;
b /= 2;
}
return res;
}
int n, m;
ll a[LIM];
ll pow2[LIM];
ll g[LIM][(1 << LIM) + 5];
ll fac[(1 << LIM) + 5], ifac[(1 << LIM) + 5];
ll C(int n, int m) {
if (n < m)
return 0;
return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> a[i];
}
sort(a + 1, a + 1 + m);
reverse(a + 1, a + 1 + m);
pow2[0] = 1;
for (int i = 1; i < LIM; i++) {
pow2[i] = pow2[i - 1] << 1ll;
}
fac[0] = 1;
for (int i = 1; i <= pow2[LIM - 1]; i++) {
fac[i] = fac[i - 1] * i % mod;
}
ifac[pow2[LIM - 1]] = qpow(fac[pow2[LIM - 1]], mod - 2);
for (int i = pow2[LIM - 1] - 1; i >= 0; i--) {
ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
}
g[0][0] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 0; j < pow2[n]; j++) {
g[i][j] = (g[i][j] + g[i - 1][j]) % mod;
for (int k = 0; k < n; k++) {
if (j & pow2[k])
continue;
g[i][(j | pow2[k])] =
(g[i][(j | pow2[k])] +
g[i - 1][j] * C(pow2[n] - j - a[i], pow2[k] - 1) % mod *
fac[pow2[k]] % mod) %
mod;
}
}
}
ll ans = 0;
for (int i = 0; i < pow2[n]; i++) {
int res = __builtin_popcount(i);
if (res & 1) {
ans = (ans - g[m][i] * fac[pow2[n] - 1 - i] + mod) % mod;
} else {
ans = (ans + g[m][i] * fac[pow2[n] - 1 - i]) % mod;
}
}
cout << ans * pow2[n] % mod;
return 0;
}