题目要求用2x1的小长方形去填满一个4xN的大长方形,问有多少种填法……如果数据不大,那完全就是一道很裸的状态压缩dp,不过这题数据大得惊人,所以就想到了矩阵的快速幂相乘,不过找相邻之间的关系那里还是挺麻烦的,这里就贴上以为牛人关于用一个dfs来找关系的解析点击打开链接。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define LL long long
#define N (1<<4)
int mod;
struct matrix
{
int mat[N][N];
}tmp,ans;
void dfs(int d,int now,int pre) //d表示第几列
{
if(d>4)return;
if(d==4)
{
tmp.mat[pre][now]++; //表示由第i-1行状态pre转移到第i行状态now的方法数
return;
}
dfs(d+1,now<<1,(pre<<1)|1); //i行不放,但i-1行应该是是有的
dfs(d+1,(now<<1)|1,pre<<1); //竖直放置,第i行增加一个状态,而第i-1行本应该就是空的,好让能放下去
dfs(d+2,(now<<2)|3,(pre<<2)|3); //横放在第i行,这时i-1行应该是满的,要不就会留空了
}
matrix mul(matrix a,matrix b)
{
matrix ant;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
ant.mat[i][j]=0;
for(int k=0;k<N;k++)
{
(ant.mat[i][j]+=a.mat[i][k]*b.mat[k][j])%=mod;
}
}
}
return ant;
}
void pow(int n,matrix Mat)
{
while(n)
{
if(n&1)ans=mul(ans,Mat);
Mat=mul(Mat,Mat);
n>>=1;
}
}
int main()
{
freopen("a.txt","r",stdin);
memset(tmp.mat,0,sizeof(tmp.mat));
dfs(0,0,0); //找相邻之间状态转移的关系
int n;
while(scanf("%d%d",&n,&mod)&&n)
{
ans=tmp;
pow(n,tmp);
printf("%d\n",ans.mat[0][N-1]);
}
return 0;
}