poj3420 Quad Tiling
Posted yzxverygood
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj3420 Quad Tiling相关的知识,希望对你有一定的参考价值。
题目大意
问讲一个大小为4*n的棋盘用无数1*2的骨牌不重叠覆盖有多少种方案。
分析
我们考虑可以将长为n的棋盘分为两块,一个大小为n-i,另一个大小为i,而为了避免对于不同的i构造出相同的情况,我们必须使长为i的那一半棋盘是一种不可分离的情况,即对于这种情况去掉其中的任意一行均不合法。我们设对于长为n的棋盘方案数为f(n),长为n的棋盘的不可分离棋盘的数量为a[n]。我们自己画一画可以得到a[1]=1,a[2]=4,a[3]=2,a[4]=3,a[5]=2,a[6]=3,不难发现当n>=2是如果n为奇数a[n]=2,否则a[n]=3。
所以我们可以得到
f(n)=f(n-1)+4f(n-2)+2f(n-3)+3f(n-4)+2f(n-5)+3f(n-6)......
我们发现
f(n-3)+4f(n-4)+2f(n-5)+3f(n-6)......=f(n-2)
所以我们可以把公式变为
f(n)=f(n-1)+5f(n-2)+f(n-3)-f(n-4)
然后我们便可以推出矩阵了。详见代码。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int n,m;
struct mat {
int g[5][5];
};
inline mat operator * (const mat a,const mat b){
mat c;
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++){
int x=0;
for(int k=1;k<=4;k++)
x=(x+a.g[i][k]*b.g[k][j]%m)%m;
c.g[i][j]=x;
}
return c;
}
inline int pw(int p){
mat a,res;
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
a.g[i][j]=0;
a.g[1][1]=a.g[1][2]=a.g[2][3]=a.g[3][1]=a.g[3][4]=1;
a.g[2][1]=5;a.g[4][1]=-1;
res=a;
while(p){
if(p&1)res=res*a;
a=a*a;
p>>=1;
}
int ans=((res.g[1][1]*36%m+m)%m+(res.g[2][1]*11%m+m)%m+
(res.g[3][1]*5%m+m)%m+(res.g[4][1]%m+m)%m)%m;
return ans;
}
int main(){
scanf("%d%d",&n,&m);
while(n&&m){
if(n<=4){
if(n==1)cout<<1%m<<endl;
else if(n==2)cout<<5%m<<endl;
else if(n==3)cout<<11%m<<endl;
else cout<<36%m<<endl;
}else printf("%d
",pw(n-5));
scanf("%d%d",&n,&m);
}
return 0;
}
以上是关于poj3420 Quad Tiling的主要内容,如果未能解决你的问题,请参考以下文章