ps:想到了要用矩阵递推,就是没找到式子。dp [ i ][ s ] : 第 i 列状态为 s 的方案数(为了方便用位运算,1表示白色,0表示黑色),剩下的找那个表达矩阵,只要状态 s1 & s2 = 0,则 s1 可以转移到 s2。
const int mod = 1000000007; struct mat { LL t; LL A[32][32]; void Inite(LL n) { t = n; mem(A, 0); } mat operator * (const mat tp) { mat ans; ans.Inite(t); rep(i, 0, t) rep(j, 0, t) rep(k, 0, t) { ans.A[i][j] += A[i][k] * tp.A[k][j]; ans.A[i][j] %= mod; } return ans; } void operator = (const mat tp) { rep(i, 0, t) rep(j, 0, t) A[i][j] = tp.A[i][j]; } }; LL n, m; mat qpow(mat C, LL x) { mat B; B.Inite((1 << m)); rep(i, 0, (1 << m)) B.A[i][i] = 1; for (; x; C = C * C, x >>= 1) { if (x & 1) B = B * C; } return B; } int main() { cin >> m >> n; mat res; res.Inite((1 << m)); for (int i = 0; i < (1 << m); ++i) { for (int j = 0; j < (1 << m); ++j) { if (!i && !j) continue; if (!(i & j)) res.A[i][j] = 1; } } res = qpow(res, n - 1); LL ans = 0; rep(i, 0, (1 << m)) rep(j, 0, (1 << m)) ans = (ans + res.A[i][j]) % mod; cout << ans << endl; return 0; }