-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path51nod-1518.cpp
66 lines (66 loc) · 1.77 KB
/
51nod-1518.cpp
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
#include <algorithm>
#include <cstring>
#include <cstdio>
#define rep(i, j, k) for(int i = j; i <= k; i ++)
#define per(i, j, k) for(int i = j; i >= k; i --)
using namespace std;
const int N = 18, mod = 1e9 + 7;
int ans[N][N], tot[N][N];
void upd(int &x, const int &y) {
(x += y) >= mod ? x -= mod : 0;
}
void solve(int n, int m) {
static int dp[2][1 << 16];
memset(dp, 0, sizeof dp); dp[0][0] = 1;
int cur = 0;
rep(i, 1, n) {
rep(j, 1, m) {
cur ^= 1; fill(dp[cur], dp[cur] + (1 << m), 0);
rep(st, 0, (1 << m) - 1) if(dp[cur ^ 1][st]) {
if(st >> (j - 1) & 1) {
upd(dp[cur][st ^ (1 << (j - 1))], dp[cur ^ 1][st]);
} else {
if(i < n)
upd(dp[cur][st ^ (1 << (j - 1))], dp[cur ^ 1][st]);
if(j < m && !(st >> j & 1))
upd(dp[cur][st | (1 << j)], dp[cur ^ 1][st]);
}
}
}
tot[i][m] = dp[cur][0];
}
}
void solve_ans(int n, int m) {
static int dp[N], f[N], a[N], cnt;
rep(i, 0, (1 << (n - 1)) - 1) {
a[cnt = 1] = 1;
rep(j, 0, n - 2) if(i >> j & 1) {
a[++ cnt] = 1;
} else a[cnt] ++;
rep(j, 1, m) {
f[j] = 1;
rep(k, 1, cnt) {
f[j] = 1ll * f[j] * tot[a[k]][j] % mod;
}
}
rep(j, 1, m) {
dp[j] = f[j];
rep(k, 1, j - 1) {
upd(dp[j], mod - 1ll * dp[k] * f[j - k] % mod);
}
}
if(__builtin_popcount(i) & 1) {
rep(j, 1, m) upd(ans[n][j], mod - dp[j]);
} else {
rep(j, 1, m) upd(ans[n][j], dp[j]);
}
}
}
int main() {
rep(m, 1, 16) solve(16, m);
rep(n, 1, 16) solve_ans(n, 16);
for(int n, m; ~ scanf("%d%d", &n, &m); ) {
printf("%d\n", ans[n][m]);
}
return 0;
}