描述:
首先,这道题是poj2663的升级版https://blog.youkuaiyun.com/q_t_pang/article/details/81077519
在一个4*n的棋盘上,用1*2的多米诺骨牌来平铺,问铺满的方法有多少种。
同样的,我们将棋盘分为左右两部分,右边部分是不可分割的。
1、当右边部分是4*1时,不可分割的只有一种铺满方法
2、当右边部分是4*2时,不可分割的有四种平铺方法
3、当右边部分是4*3时,不可分割的有两种平铺方法
4、当右边部分是4*4时,不可分割的有3种平铺方法
当往下继续推倒时发现,当n为奇数且n>=3时,不可分割的平铺方法为2;当n为偶数且n>=4时,不可分割的平铺方法为3;
所以,f(n)=f(n-1)*b(1)+f(n-2)*b(2)+f(n-3)*b(3)+f(n-4)*b(4)+…+f(0)*b(n)
即f(n)=f(n-1)+f(n-2)*4+f(n-3)*2+f(n-4)*3+…+f(0)*b(n)
下面求解上述表达式
f(n-1)=f(n-2)+f(n-3)*4+f(n-4)*2+f(n-5)*3+…+f(0)*b(n-1)
上述两个表达式相加可得
f(n)=5*f(n-2)+6*f(n-3)+5*(f(n-4)+f(n-5)+…+f(0))
所以f(n-1)=5*f(n-3)+6*f(n-4)+5*(f(n-5)+f(n-6)+…+f(0))
上述两个表达式相减可得
f(n)-f(n-1)=5*f(n-2)+f(n-3)-f(n-4)
所以最终可得f(n)=f(n-1)+5*f(n-2)+f(n-3)-f(n-4)
但由于本题所给范围很大,我们需要用矩阵快速幂的方法节省时间
矩阵求解上述问题的方法详述
a[n-3] 0 1 0 0 a[n-4] |
a[n-2] = 0 0 1 0 * a[n-3] |
a[n-1] 0 0 0 1 a[n-2] |
a[n] -1 1 5 1 a[n-1] |
另中间的矩阵为T,初始(a[0] a[1] a[2] a[3])为A
那么A=T(r-3)次幂 * A(注意:矩阵乘法没有交换率)
求T的n次幂时采用矩阵快速幂的方法
#include<iostream>
#include<string.h>
using namespace std;
const int MAXN=10;
const int MAXM=10;
int r,mod;
//矩阵类模板
struct Matrix{
int n,m;
int a[MAXN][MAXM];
void clear(){
n=m=0;
memset(a,0,sizeof(a));
}
Matrix operator +(const Matrix &b) const {
Matrix tmp;
tmp.n=n;tmp.m=m;
for (int i=0;i<n;++i)
for(int j=0;j<m;++j)
tmp.a[i][j]=a[i][j]+b.a[i][j];
return tmp;
}
Matrix operator -(const Matrix &b)const{
Matrix tmp;
tmp.n=n;tmp.m=m;
for (int i=0;i<n;++i)
for(int j=0;j<m;++j)
tmp.a[i][j]=a[i][j]-b.a[i][j];
return tmp;
}
Matrix operator * (const Matrix &b) const{
Matrix tmp;
tmp.clear();
tmp.n=n;tmp.m=b.m;
for (int i=0;i<n;++i)
for(int j=0;j<b.m;++j)
for (int k=0;k<m;++k){
tmp.a[i][j]+=a[i][k]*b.a[k][j];
tmp.a[i][j]%=mod;
}
return tmp;
}
Matrix get(int x){//幂运算
Matrix E;
E.clear();
E.n=E.m=n;
for(int i=0;i<n;++i)
E.a[i][i]=1;
if(x==0) return E;
else if(x==1) return *this;
Matrix tmp=get(x/2);
tmp=tmp*tmp;
if(x%2) tmp=tmp*(*this);
return tmp;
}
};
//矩阵模板结束
int main(){
while(cin>>r>>mod){
if(r==0) break;
int a[]= {1,1,5,11};
if(r<=3)
{
cout<<a[r]%mod<<endl;
continue;
}
Matrix A;
A.clear();
A.n=A.m=4;
A.a[0][1]=A.a[1][2]=A.a[2][3]=1;
A.a[3][0]=-1;
A.a[3][1]=1;
A.a[3][2]=5;
A.a[3][3]=1;
A=A.get(r-3);
Matrix M;
M.clear();
M.n=4;M.m=1;
M.a[0][0]=M.a[1][0]=1;
M.a[2][0]=5;
M.a[3][0]=11;
M=A*M;
cout<<(M.a[3][0]+mod)%mod<<endl;
}
return 0;
}