题意:
给出n和m,在一个4xn的地面上铺1x2的骨牌,求方案数;
答案对m取模,多组数据;
题解:
这个显然就是骨牌覆盖问题嘛;
状压dp搞一搞就好啦;
然后我RE+TLE之后发现,n<=109
这个就不好搞了,要用log级算法才行;
于是就用矩阵乘法,做一个16x16的矩阵,表示各种状态之间的转移;
初始矩阵就是a[0][0]=1,其他为0;
至于用来快速幂的矩阵我用TLE的程序跑了一个,手算也行吧(笑);
(反正如果我手算估计wa一天)
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define L 16
using namespace std;
typedef long long ll;
ll mod,f[100][100];
struct matrix
{
ll a[L][L];
}In,st,en,T;
matrix mul(matrix x,matrix y)
{
matrix ret;
ll i,j,k;
for(i=0;i<L;i++)
for(j=0;j<L;j++)
for(k=0,ret.a[i][j]=0;k<L;k++)
ret.a[i][j]=(ret.a[i][j]+(x.a[i][k]*y.a[k][j]))%mod;
return ret;
}
matrix pow(matrix x,ll y)
{
matrix ret=In;
while(y)
{
if(y&1)
{
ret=mul(ret,x);
}
y>>=1;
x=mul(x,x);
}
return ret;
}
int main()
{
ll n,m,i,j,k;
T.a[0][0]=1; T.a[0][3]=1; T.a[0][9]=1;
T.a[0][12]=1; T.a[1][2]=1; T.a[1][8]=1;
T.a[1][14]=1; T.a[2][1]=1; T.a[2][13]=1;
T.a[3][0]=1; T.a[3][12]=1; T.a[4][8]=1;
T.a[4][11]=1; T.a[5][10]=1; T.a[6][9]=1;
T.a[7][8]=1; T.a[8][1]=1; T.a[8][4]=1;
T.a[8][7]=1; T.a[9][0]=1; T.a[9][6]=1;
T.a[10][5]=1; T.a[11][4]=1; T.a[12][0]=1;
T.a[12][3]=1; T.a[13][2]=1; T.a[14][1]=1;
T.a[15][0]=1; T.a[0][15]=1;
for(i=0;i<L;i++) In.a[i][i]=1;
while(scanf("%lld%lld",&n,&m)&&(n||m))
{
mod=m;
st.a[0][0]=1;
en=mul(st,pow(T,n));
printf("%lld\n",en.a[0][0]);
}
}