题意:给出一个 n × m n×m n×m的方格图,现在要用如下L型的占3个的积木拼到这个图中,总共有多少种拼法使图满。
cpp
#include<bits/stdc++.h>
using namespace std;
long long n,m,k=1,Now;
int Mod=1000000007;
struct Matrix
{
long long a[129][129];
Matrix(){for(long long i=0;i<k;i++)a[i][i]=1;}
Matrix(int x){memset(a,0,sizeof(a));}
Matrix operator*(Matrix& B)//矩阵乘法
{
Matrix t(0);
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
for(int l=0;l<k;l++)
t.a[i][j]=(t.a[i][j]+a[i][l]*B.a[l][j])%Mod;
return t;
}
};
Matrix quickmul(Matrix ans,long long p)//矩阵快速幂
{
Matrix t;
while(p)
{
if(p&1)t=t*ans;
ans=ans*ans;
p>>=1;
}
return t;
}
Matrix A(0);
void dfs(int now,int next)
{
//cout<<now<<" "<<next<<endl;
if(now+1==k)
{
A.a[Now][next]++;
return ;
}
for(int l=0;l<m;l++)
{
if((now>>l)&1)continue;//当前列的位置上有拼图则跳过
int temp=1<<l;
int now1,next1;//递归,四种拼图
now1=temp|(temp<<1);// 1 1
next1=temp; // 0 1
if((l+1<m)&&!(now&now1||next&next1))dfs(now1|now,next1|next);
now1=temp|(temp<<1);// 1 1
next1=temp<<1; // 1 0
if((l+1<m)&&!(now&now1||next&next1))dfs(now1|now,next1|next);
now1=temp; // 0 1
next1=temp|temp<<1; // 1 1
if((l+1<m)&&!(now&now1||next&next1))dfs(now1|now,next1|next);
now1=temp; // 1 0
next1=temp|temp>>1; // 1 1
if((l)&&!(now&now1||next&next1))dfs(now1|now,next1|next);
return ;
}
}
int main()
{
cin>>n>>m;
for(long long i=0;i<m;i++)k<<=1;
for(Now=0;Now<k;Now++)dfs(Now,0);
Matrix ANS=quickmul(A,n);
/*for(int i=0;i<k;i++)
{
for(int j=0;j<k;j++)cout<<ANS.a[i][j]<<" ";
cout<<endl;
}*/
cout<<ANS.a[0][0]<<endl;
return 0;
}