# 【BZOJ4417】[Shoi2013]超级跳马

3 5

10

## HINT

P.S:同学提供了一个更巧妙的做法，令方程为f[i][j]=f[i-2][j]+f[i-1][j-1]+f[i-1][j]+f[i-1][j+1]，然后维护个100*100的矩阵就行了。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int P=30011;
int n,m;
struct M
{
int a[160][160];
int * operator [] (int b) {return a[b];}
M () {memset(a,0,sizeof(a));}
M operator * (M b)
{
M c;	int i,j,k;
for(i=1;i<=3*n;i++)	for(j=1;j<=3*n;j++)	for(k=1;k<=3*n;k++)	c[i][j]=(c[i][j]+a[i][k]*b[k][j])%P;
return c;
}
};
M ans,A,B,C;
void pm(int y)
{
while(y)
{
if(y&1)	ans=ans*C;
C=C*C,y>>=1;
}
}
int main()
{
scanf("%d%d",&n,&m),m--;
int i;
ans[1][1]=ans[1][2*n+1]=1;
for(i=1;i<=n;i++)
{
if(i>1)	A[2*n+i][i-1]=A[2*n+i][n+i-1]=B[n+i][i-1]=B[n+i][2*n+i-1]=1;
A[2*n+i][i]=A[2*n+i][n+i]=A[2*n+i][2*n+i]=A[n+i][n+i]=B[n+i][i]=B[n+i][n+i]=B[n+i][2*n+i]=B[2*n+i][2*n+i]=1;
if(i<n)	A[2*n+i][i+1]=A[2*n+i][n+i+1]=B[n+i][i+1]=B[n+i][2*n+i+1]=1;
}
C=A*B;
pm(m>>1);
if(m&1)	ans=ans*A;
printf("%d",ans[1][n]);
return 0;
}

posted @ 2017-09-20 14:53  CQzhangyu  阅读(289)  评论(0编辑  收藏  举报