每行结尾连续的1的个数只能是0,1,2。
状态记录一下有几行结尾连续的1的个数为0,几行结尾连续的1的个数为1,当前有多少列为全1。
然后矩乘转移就好了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
int n,P,Q,cnt,ans;
ll m;
struct Matrix
{
int w[185][185];
void init()
{
memset(w,0,sizeof(w));
for(int i=1;i<=cnt;i++)w[i][i]=1;
}
}mat,tmp;
void mul(Matrix &a,Matrix &b,Matrix &c)
{
memset(&tmp,0,sizeof(tmp));
for(int i=1;i<=cnt;i++)
for(int k=1;k<=cnt;k++)if(a.w[i][k])
for(int j=1;j<=cnt;j++)if(b.w[k][j])
tmp.w[i][j]=(tmp.w[i][j]+(ll)a.w[i][k]*b.w[k][j])%mod;
c=tmp;
}
int num[5][11][11],C[11][11];
Matrix qpow(Matrix x,ll y)
{
Matrix ret;ret.init();
while(y)
{
if(y&1)mul(ret,x,ret);
mul(x,x,x);y>>=1;
}
return ret;
}
int main()
{
scanf("%d%lld%d%d",&n,&m,&P,&Q);
if(P==1)return puts("1"),0;
for(int i=0;i<=n;i++)C[i][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
C[i][j]=C[i-1][j-1]+C[i-1][j];
for(int i=0;i<=Q;i++)
for(int j=0;j<=n;j++)
for(int k=0;j+k<=n;k++)
if(P!=2||j+k==n)
num[i][j][k]=++cnt;
for(int i=0;i<=Q;i++)
for(int a1=0;a1<=n;a1++)
for(int b1=0;b1+a1<=n;b1++)
if(P!=2||a1+b1==n)
{
int t1=num[i][a1][b1];
for(int a2=0;a2<=a1;a2++)
for(int b2=0;b2<=b1;b2++)
if(P!=2||b2==0)
{
int t2=num[i+(a2+b2==n)][(n-a1-b1)+(a1-a2)+(b1-b2)][a2];
if(i+(a2+b2==n)>Q)continue;
(mat.w[t1][t2]+=C[a1][a2]*C[b1][b2])%=mod;
}
}
mat=qpow(mat,m);
int t=num[0][n][0];
for(int i=1;i<=cnt;i++)
ans=(ans+mat.w[t][i])%mod;
printf("%d\n",ans);
return 0;
}