Description:
n<=12,m<=30
题解:
很容易想到一种一行一行的dp,我们觉得n太小了,想一列一列做,发现不行。
然后脑洞打开,直接斜着dp,发现就没有了。
Code:
#include<cstdio>
#include<cstring>
#define pp printf
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
using namespace std;
const int N = 31;
int n, m, mo, a2[14];
int a[N * N][2], a0, b[N * N][2], b0, x, y;
int o, m2;
ll f[2][1 << 13], g[2][1 << 13];
#define w(x, y) ((x) >> (y) & 1)
int zz(int k, int d) {
int nn = (x == n || y == 1) ? 0 : w(k, x) * a2[n];
if(w(k, x)) k -= a2[x];
if(w(k, n)) k -= a2[n];
if(d == 1) k += a2[x - 1];
if(d == 2) k += a2[x];
return k + nn;
}
int main() {
freopen("bear.in", "r", stdin);
freopen("bear.out", "w", stdout);
a2[0] = 1; fo(i, 1, 13) a2[i] = a2[i - 1] << 1;
scanf("%d %d %d", &n, &m, &mo);
fo(i, 1, n) a[++ a0][0] = i, a[a0][1] = 1;
fo(j, 2, m) a[++ a0][0] = n, a[a0][1] = j;
m2 = a2[n + 1] - 1;
f[o][0] = 1;
fo(i, 1, a0 - 1) {
b0 = 0;
x = a[i][0], y = a[i][1];
while(x > 0 && y <= m)
b[++ b0][0] = x, b[b0][1] = y, x --, y ++;
fd(j, b0, 1) {
memset(f[!o], 0, sizeof f[!o]);
memset(g[!o], 0, sizeof g[!o]);
x = b[j][0], y = b[j][1];
fo(k, 0, m2) if(f[o][k]) {
f[o][k] %= mo;
g[o][k] %= mo;
int z1 = w(k, n), z2 = y == m ? 1 : w(k, x - 1), z3 = x == n ? 1 : 0;
if(z1 || z2 && z3) {
int nk = zz(k, 0);
f[!o][nk] += f[o][k] * 2;
g[!o][nk] += g[o][k] * 2;
} else
if(z2 && !z3) {
int nk = zz(k, 2);
f[!o][nk] += f[o][k] * 2;
g[!o][nk] += (g[o][k] + f[o][k]) * 2;
} else
if(!z2 && z3) {
int nk = zz(k, 1);
f[!o][nk] += f[o][k] * 2;
g[!o][nk] += (g[o][k] + f[o][k]) * 2;
} else {
int nk = zz(k, 1);
f[!o][nk] += f[o][k];
g[!o][nk] += (g[o][k] + f[o][k]);
nk = zz(k, 2);
f[!o][nk] += f[o][k];
g[!o][nk] += (g[o][k] + f[o][k]);
}
}
o = !o;
}
memset(f[!o], 0, sizeof f[!o]);
memset(g[!o], 0, sizeof g[!o]);
x = a[i + 1][0], y = a[i + 1][1];
while(x > 0 && y <= m) x --, y ++;
int p = x;
fo(k, 0, m2) if(f[o][k]) {
int nk = k - w(k, p) * a2[p] + a2[n] * w(k, p);
f[!o][nk] += f[o][k];
g[!o][nk] += g[o][k];
}
o = !o;
}
ll ans = 0;
fo(k, 0, m2) ans = (ans + g[o][k]) % mo;
pp("%lld\n", ans * 2 % mo);
}