#include <bits/stdc++.h>
using namespace std;
#define int __int128
long long n, m;
int nxt[531441*3][3], val[531441*3], nodet;
int ans = 0;
char s[129][129];
struct Info {
char s[16];
int hashv() {
int now = 0;
for (int i = 1; i <= m; ++i) {
if (!nxt[now][s[i]]) {
nxt[now][s[i]] = ++nodet;
}
now = nxt[now][s[i]];
}
if (!val[now]) val[now] = ++ans;
return val[now];
}
char & operator [](const int a) {
return s[a];
}
};
__int128 dp[22][12][18898];
// 0 表无插头,1 表左括号,2 表右括号
__int128 dfs(int i, int j, Info f) {
// printf("%d %d\n", i, j);
// for (int k = 1; k <= m + 1; ++k) printf("%d%c", f[k], " \n"[k == m + 1]);
if (i == n + 1) {
for (int k = 1; k <= m + 1; ++k) {
if (f[k]) return 0;
}
return 1;
}
if (j == m + 1) {
if (f[j]) return 0;
Info newf = {};
for (int k = 1; k <= m; ++k) {
newf[k + 1] = f[k];
}
return dfs(i + 1, 1, newf);
}
if (s[i][j] == '*') {
if (f[j] || f[j + 1]) return 0;
return dfs(i, j + 1, f);
}
int hs = f.hashv();
if (dp[i][j][hs] != -1) return dp[i][j][hs];
if (f.s[j] == 0 && f.s[j + 1] == 0) {
f.s[j] = 1;
f.s[j + 1] = 2;
return dp[i][j][hs] = dfs(i, j + 1, f);
} else if (f[j] == 0 && f[j + 1] == 2) {
__int128 ans = dfs(i, j + 1, f);
f[j] = 2;
f[j + 1] = 0;
return dp[i][j][hs] = ans + dfs(i, j + 1, f);
} else if (f[j] == 0 && f[j + 1] == 1) {
__int128 ans = dfs(i, j + 1, f);
f[j] = 1;
f[j + 1] = 0;
return dp[i][j][hs] = ans+ dfs(i, j + 1, f);
} else if (f[j] == 2 && f[j + 1] == 2) {
int st[14] = {}, top = 0, tmp[3] = {}, tot = 0;
for (int k = 1; k <= m + 1; ++k) {
if (f[k] == 1) st[++top] = k;
else if (f[k] == 2) {
if (k == j) tmp[++tot] = st[top];
if (k == j + 1) tmp[++tot] = st[top];
--top;
}
}
f[min(tmp[1], tmp[2])] = 1;
f[max(tmp[1], tmp[2])] = 2;
f[j] = f[j + 1] = 0;
return dp[i][j][hs] = dfs(i, j + 1, f);
} else if (f[j] == 2 && f[j + 1] == 1) {
f[j] = 0;
f[j + 1] = 0;
return dp[i][j][hs] = dfs(i, j + 1, f);
} else if (f[j] == 2 && f[j + 1] == 0) {
__int128 ans = dfs(i, j + 1, f);
f[j] = 0, f[j + 1] = 2;
return dp[i][j][hs] = ans+ dfs(i, j + 1, f);
} else if (f[j] == 1 && f[j + 1] == 2) {
if (i == n && j == m) {
for (int k = 1; k <= m - 1; ++k) if (f[k]) return dp[i][j][hs] = 0;
return dp[i][j][hs] = 1;
} else return dp[i][j][hs] = 0;
} else if (f[j] == 1 && f[j + 1] == 1) {
int st[14] = {}, top = 0, tmp[5], tot = 0;
for (int k = 1; k <= m + 1; ++k) {
if (f[k] == 1) st[++top] = k;
else if (f[k] == 2) {
if (st[top] == j) tmp[++tot] = k;
if (st[top] == j + 1) tmp[++tot] = k;
--top;
}
}
f[min(tmp[1], tmp[2])] = 1;
f[max(tmp[1], tmp[2])] = 2;
f[j] = f[j + 1] = 0;
return dp[i][j][hs] = dfs(i, j + 1, f);
} else if (f[j] == 1 && f[j + 1] == 0) {
__int128 ans = dfs(i, j + 1, f);
f[j] = 0, f[j + 1] = 1;
return dp[i][j][hs] = ans + dfs(i, j + 1, f);
} else return 0;
}
void write(__int128 i, bool fir = 0) {
if (i == 0) {
if (!fir) putchar('0');
return;
}
write(i / 10, 1); putchar(i % 10 + '0');
}
signed main() {
scanf("%lld%lld", &m, &n);
if (n == 1 || m == 1)return puts("1"), 0;
memset(dp, 255, sizeof(dp));
write(dfs(1, 1, {}) * 2);
return 0;
}
直接套的板子,所以会出现 s[i][j] 这个神奇的东西。
然后 f[i]=0 表示对应轮廓线上无插头,f[i]=1 表示对应轮廓线上有一个插头,且代表的是左括号,f[i]=2 同理。
哈希用的是字典树哈希。
用记忆化搜索写的。