点击前往试题目录:https://blog.csdn.net/best335/article/details/99550556
思路:状态压缩+矩阵快速幂运算
解析:
----状态压缩:所要求得的拼法=第一行全部不填转移到的第二行的各种填法+由为第二行初始状态转移到第三行的各种填法…一直到由n-1行的状态转移到第n行全部填满的状态总和
----矩阵快速幂:A8=A * A * A * A * A * A * A * A = A4 * A4 ; A4=A2 * A2;
只需要O(logn * (1<<m)3)就可以把矩阵An求出来,而常规方式需要O(n * (1<<m)3)。
参考:https://blog.csdn.net/blzorro/article/details/41786121
#include<iostream>
#include<cstring>
using namespace std;
long long S[128][128];
struct Matrix{
long long mat[128][128];
int m,n;
Matrix(const int&m,const int&n,const bool& init = true):m(m),n(n){
if(init)
for(int i=0;i<m;++i)
for(int j=0;j<n;++j)
mat[i][j]=i==j?1LL:0LL;
else
memset(mat,0,sizeof(mat));
}
Matrix(const int&m,const int& n,const long long mat[128][128]){
for(int i=0;i<m;++i)
for(int j=0;j<n;++j)
this->mat[i][j]=mat[i][j];
this->m=m,this->n=n;
}
Matrix& operator*(const Matrix&m){
Matrix mtx(m.m,m.n,false);
for(int i=0;i<this->m;++i)
for(int j=0;j<m.n;++j)
for(int k=0;k<n;++k)
mtx.mat[i][j]=(mtx.mat[i][j]+mat[i][k]*m.mat[k][j])%1000000007LL;
memcpy(mat,mtx.mat,sizeof(mat));
return *this;
}
friend Matrix& operator^(Matrix&m,long long n){
Matrix u(m.m,m.n);
while(n){
if(n&1) u=u*m;
m=m*m;
n>>=1;
}
memcpy(m.mat,u.mat,sizeof(m.mat));
return m;
}
};
void getStatus(const int& s,short l1,short l2,const int&k,const int&n){
if(l1==(1<<n)-1) ++S[l2][s];
else{
for(int i=k;i<n;++i){
bool b11=i>0&&(l1&(1<<(i-1)))==0,b12=(l1&(1<<i))==0,b13=b11&&b12,b21=i>0&&(l2&(1<<(i-1)))==0,b22=(l2&(1<<i))==0,b23=b21&&b22;
short l11=i>0?l1|(1<<(i-1)):l1,l12=l1|1<<i,l13=l11|l12,l21=i>0?l2|(1<<(i-1)):l2,l22=l2|1<<i,l23=l21|l22;
if(b13&&b21) getStatus(s,l13,l21,i+1,n);//,cout<<s<<" "<<k<<" "<<l1<<" "<<l2<<" "<<l13<<" "<<l21<<endl;//└
if(b13&&b22) getStatus(s,l13,l22,i+1,n);//,cout<<s<<" "<<k<<" "<<l1<<" "<<l2<<" "<<l13<<" "<<l22<<endl;//┘
if(b11&&b23) getStatus(s,l11,l23,i+1,n);//,cout<<s<<" "<<k<<" "<<l1<<" "<<l2<<" "<<l11<<" "<<l23<<endl;//┌
if(b12&&b23) getStatus(s,l12,l23,i+1,n);//,cout<<s<<" "<<k<<" "<<l1<<" "<<l2<<" "<<l12<<" "<<l23<<endl;//┐
}
}
}
int main(){
long long n,m;
memset(S,0,sizeof(S));
cin>>n>>m;
for(int i=0,ni=1<<m;i<ni;++i)getStatus(i,i,0,0,m);
Matrix D(1<<m,1<<m,S);
cout<<(D^n).mat[(1<<m)-1][(1<<m)-1]<<endl;
return 0;
}