题解 P3990 [SHOI2013]超级跳马
显然有 DP 做法,$f(i,j)$ 表示走到第 $i$ 行第 $j$ 列的方案数量。
有转移方程$$f(i,j)=f(i-1,j-1)+f(i,j-1)+f(i+1,j-1)+\sum\limits_{i=1}^{\left\lfloor{\frac{j}{2}}\right\rfloor}f(i-1,j-1-2i)+f(i,j-1-2i)+f(i+1,j-1-2i)$$
这个转移方程转移复杂度太高,发现后面那个式子即为 $f(i,j-2)$。
所以有更简洁的转移方程$$f(i,j)=f(i-1,j-1)+f(i,j-1)+f(i+1,j-1)+f(i,j-2)$$
然后发现,数据范围 $n\le50,m\le10^9$,暴力转移 $O(nm)$,过高。
考虑用矩阵优化。
矩阵中有上两列每行的状态。如 $n=3$ 时有转移矩阵
$\begin{bmatrix}1&1&0&1&0&0\\1&1&1&0&1&0\\0&1&1&0&0&1\\1&0&0&0&0&0\\0&1&0&0&0&0\\0&0&1&0&0&0\end{bmatrix}\times\begin{bmatrix}f(1,i-1)\\f(2,i-1)\\f(3,i-1)\\f(1,i-2)\\f(2,i-2)\\f(3,i-2)\end{bmatrix}=\begin{bmatrix}f(1,i)\\f(2,i)\\f(3,i)\\f(1,i-1)\\f(2,i-1)\\f(3,i-1)\end{bmatrix}$
这个矩阵的构造,以 $f(2,i)$ 为例$$f(2,i)=1\times f(1,i-1)+1\times f(2,i-1)+1\times f(3,i-1)+0\times f(1,i-2)+1\times f(2,i-2)+0\times f(3,i-2)$$
其对应的系数即为初始矩阵的第 $2$ 行。
矩阵快速幂即可。
因为最初第一列不需要转移,所以将 $m\gets m-1$,并特判一下 $m=2$ 的情况,然后会发现,在 计算 $f(1,3)$ 时,会有从 $f(1,1)$ 来的转移,然而 $f(1,1)$ 并没有在其之前列的转移,导致多算了一次。所以到 $f(n,m)$ 时,多出的方案数,即为从 $(1,1)$ 到 $(n,m-2)$ 的方案数,即多出 $f(n,m-2)$,减去它即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10, P = 30011;
int n, m;
struct Matrix {
int a[N][N];
Matrix() { memset(a, 0, sizeof(a)); }
void init() {
for(int i = 1; i <= (n << 1); i++) a[i][i] = 1;
}
friend Matrix operator * (Matrix a, Matrix b) {
Matrix res;
for(int i = 1; i <= (n << 1); i++)
for(int j = 1; j <= (n << 1); j++)
for(int k = 1; k <= (n << 1); k++)
res.a[i][j] = (res.a[i][j] + a.a[i][k] * b.a[k][j]) % P;
return res;
}
} base;
Matrix qpow(Matrix a, int k) {
Matrix res; res.init();
for(; k; a = a * a, k >>= 1)
if(k & 1) res = res * a;
return res;
}
void build() {
for(int i = 1; i <= n; i++)
for(int j = max(i - 1, 1); j <= min(i + 1, n); j++)
base.a[i][j] = 1;
for(int i = 1; i <= n; i++)
base.a[i][i + n] = base.a[i + n][i] = 1;
}
int main() {
scanf("%d%d", &n, &m);
if(m == 2) {
if(n <= 2) printf("1");
else printf("0");
return 0;
}
build();
m -= 2;//因为最后有一次单独算,所以m多减1
Matrix ans = qpow(base, m);
int s = ans.a[1][n << 1];
ans = ans * base;
int t = ans.a[1][n];
printf("%d", (t - s + P) % P);
return 0;
}

浙公网安备 33010602011771号