题目链接
题解:我们设
f[i][j]
f
[
i
]
[
j
]
为跳到
f[i][j]
f
[
i
]
[
j
]
的位置的方案总数。
则显然
f[i][j]=∑i2k=1f[i−1][j−2∗k+1]+f[i][j−2∗k+1]+f[i+1][j−2∗k+1]
f
[
i
]
[
j
]
=
∑
k
=
1
i
2
f
[
i
−
1
]
[
j
−
2
∗
k
+
1
]
+
f
[
i
]
[
j
−
2
∗
k
+
1
]
+
f
[
i
+
1
]
[
j
−
2
∗
k
+
1
]
这样做显然会超时。
我们再设
g[i][j]
g
[
i
]
[
j
]
为分别跳到i这一行,距离j奇数格的所有格子的方案总数。
则
f[i][j]=g[i−1][j−2]+f[i−1][j−1]+g[i][j−2]+f[i][j−1]+g[i+1][j−2]+f[i+1][j−1]
f
[
i
]
[
j
]
=
g
[
i
−
1
]
[
j
−
2
]
+
f
[
i
−
1
]
[
j
−
1
]
+
g
[
i
]
[
j
−
2
]
+
f
[
i
]
[
j
−
1
]
+
g
[
i
+
1
]
[
j
−
2
]
+
f
[
i
+
1
]
[
j
−
1
]
g[i][j]=g[i][j−2]+f[i][j−1]
g
[
i
]
[
j
]
=
g
[
i
]
[
j
−
2
]
+
f
[
i
]
[
j
−
1
]
然后矩阵快速幂加速计算即可。
我的矩阵大小是3*n的,还被xsy卡常了,所以以后矩阵乘法我再也不写在结构体里面了= =
代码:
#include<cstdio>
#include<cstring>
const int mod=30011;
int n,m,res[155][155],base[155][155],tmp[155][155];
void times(int a[][155],int b[][155]){
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=3*n;i++){
for(int j=1;j<=3*n;j++){
for(int k=1;k<=3*n;k++){
tmp[i][j]+=a[i][k]*b[k][j]%mod;
tmp[i][j]=tmp[i][j]>=mod?tmp[i][j]-mod:tmp[i][j];
}
}
}
for(int i=1;i<=3*n;i++){
for(int j=1;j<=3*n;j++){
a[i][j]=tmp[i][j];
}
}
}
int main(){
scanf("%d%d",&n,&m);
if(m==1){
if(n==1){
puts("1");
}else{
puts("0");
}
return 0;
}
res[1][n+1]=1;
for(int i=1;i<=n;i++){
base[2*n+i][i]=1;
if(i-1>0){
base[i-1][n+i]=1;
base[n+i-1][n+i]=1;
}
base[i][n+i]=1;
base[n+i][n+i]=1;
base[i][2*n+i]=1;
base[n+i][2*n+i]=1;
if(i+1<=n){
base[i+1][n+i]=1;
base[n+i+1][n+i]=1;
}
}
m--;
while(m){
if(m&1){
times(res,base);
}
m>>=1;
times(base,base);
}
printf("%d\n",res[1][2*n]);
return 0;
}