题意
自己看
题解
你就随便矩阵快速幂一下就可以了
首先这题不难想到一个nm的做法,就是保存奇数列和偶数列的答案
看看代码就懂了吧
#include<cstdio>
#include<cstring>
const int N=55;
int f[N][2];//哪一行 0:奇数列 1:偶数列
int n,m;
int main()
{
scanf("%d%d",&n,&m);
memset(f,0,sizeof(f));
f[1][0]=1;int now=0;
for (int u=2;u<m;u++)
{
for (int i=1;i<=n;i++)
{
f[i][now^1]+=f[i-1][now]+f[i][now]+f[i+1][now];
}
now^=1;
}
printf("%d\n",f[n][now]+f[n-1][now]);
return 0;
}
然后你就可以尝试构造一个矩阵,让他快速幂一下
方法有很多
着这里是吧相邻的两列放在一起快速幂
矩阵大小1*(2n)
1~n是奇数位的和 n+1~2*n是偶数位的和
然后大力推他由上一个状态怎么推过来。。
for (LL u=1;u<=n;u++)//先把前面的搞好
{
b.f[u][u]=1;
b.f[u+n][u]=1;
if (u>1) b.f[u+n][u-1]=1;
if (u<n) b.f[u+n][u+1]=1;
}
for (LL u=n+1;u<=2*n;u++)
{
b.f[u][u]++;
/*对应自己*/
b.f[u-n][u]++;
if (u+1<=2*n) b.f[u+1][u]++;
b.f[u][u]++;
if (u-1>n) b.f[u-1][u]++;
/*对应+1*/
if (u<2*n)
{
b.f[u-n+1][u]++;
b.f[u][u]++;
if (u+1<=2*n) b.f[u+1][u]++;
if (u+2<=2*n) b.f[u+2][u]++;
}
/*对应-1*/
if (u>n+1)
{
b.f[u][u]++;
b.f[u-n-1][u]++;
if (u-1>n) b.f[u-1][u]++;
if (u-2>n) b.f[u-2][u]++;
}
}
小于n位的情况是比较直观的
但是大于n的位就要要论一下了,因为他需要转移的状态在上一个矩阵没有直观地出现。。于是要手完一下
然后就快速幂一下就好了。
要注意n=1的情况,否则会WA(但是对拍时抄了一个人的代码,他的没判,对拍挂了,交上去A了,我也不知道为什么)
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const LL N=55;
const LL MOD=30011;
struct qt
{
LL x,y;//大小
LL f[N*2][N*2];
friend qt operator * (qt a,qt b)
{
qt c;c.x=a.x;c.y=a.y;
memset(c.f,0,sizeof(c.f));
for (LL u=1;u<=a.x;u++)//行
for (LL i=1;i<=a.y;i++)//列
for (LL j=1;j<=a.y;j++)
c.f[u][i]=(c.f[u][i]+(a.f[u][j]*b.f[j][i])%MOD)%MOD;
return c;
}
};//矩阵
qt a;//初始矩阵
qt b;//拿来乘的矩阵
LL n,m;
void prepare ()//构造初始矩阵
{
a.x=1;a.y=2*n;a.f[1][1]=1;a.f[1][n+1]=1;a.f[1][n+2]=1;
b.x=2*n;b.y=2*n;
for (LL u=1;u<=n;u++)//先把前面的搞好
{
b.f[u][u]=1;
b.f[u+n][u]=1;
if (u>1) b.f[u+n][u-1]=1;
if (u<n) b.f[u+n][u+1]=1;
}
for (LL u=n+1;u<=2*n;u++)
{
b.f[u][u]++;
/*对应自己*/
b.f[u-n][u]++;
if (u+1<=2*n) b.f[u+1][u]++;
b.f[u][u]++;
if (u-1>n) b.f[u-1][u]++;
/*对应+1*/
if (u<2*n)
{
b.f[u-n+1][u]++;
b.f[u][u]++;
if (u+1<=2*n) b.f[u+1][u]++;
if (u+2<=2*n) b.f[u+2][u]++;
}
/*对应-1*/
if (u>n+1)
{
b.f[u][u]++;
b.f[u-n-1][u]++;
if (u-1>n) b.f[u-1][u]++;
if (u-2>n) b.f[u-2][u]++;
}
}
}
qt shen (qt x,LL y)
{
/*printf("%d\n",y);
if (y==1) return x;
printf("YES\n");
qt lalal=shen(x,y/2);
lalal=lalal*lalal;
printf("NO");
if (y%2!=0) lalal=lalal*x;
return lalal;*/
qt ans;ans.x=x.x;ans.y=x.y;
for(int i=1;i<=ans.x;i++) ans.f[i][i]=1;
while(y)
{
if(y&1) ans=ans*x;
x=x*x;y>>=1;
}
return ans;
}
void solve ()
{
LL t=(m-2)/2;
a=a*shen(b,t);
if (m%2!=0)
{
if (n!=1) printf("%lld\n",(a.f[1][n+n]+a.f[1][n+n-1])%MOD);
else printf("%lld\n",a.f[1][2*n]);
}
else
{
if (n!=1) printf("%lld\n",(a.f[1][n]+a.f[1][n-1])%MOD);
else printf("%lld\n",a.f[1][n]);
}
}
int main()
{
scanf("%lld%lld",&n,&m);
prepare();
solve();
return 0;
}