#1162 : 骨牌覆盖问题·三
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
前两周里,我们讲解了2xN,3xN骨牌覆盖的问题,并且引入了两种不同的递推方法。
这一次我们再加强一次题目,对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数。
输入
第1行:2个整数N。表示棋盘宽度为k,长度为N。2≤K≤7,1≤N≤100,000,000
输出
第1行:1个整数,表示覆盖方案数 MOD 12357
-
样例输入
-
2 62247088
样例输出
-
1399
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MOD=12357; int m,n; struct Lu { int mx[140][140]; }L1,L2; void dfs(int now,int next,int col) { if(col==m){ L1.mx[now][next]=1;//表示now状态能够转移到next状态 return; } dfs((now<<1)+1,next<<1,col+1);//不放 dfs(now<<1,(next<<1)+1,col+1);//竖放 if(col+2<=m) dfs((now<<2)+3,(next<<2)+3,col+2);//横放 } Lu multi(Lu a,Lu b) { Lu c; for(int i=0;i<(1<<m);i++){ for(int j=0;j<(1<<m);j++){ c.mx[i][j]=0; for(int k=0;k<(1<<m);k++) c.mx[i][j]=(c.mx[i][j]+a.mx[i][k]*b.mx[k][j])%MOD; } } return c; } int solve(int x) { memcpy(L2.mx,L1.mx,sizeof(L1.mx)); while(x){ if(x&1) L1=multi(L1,L2); L2=multi(L2,L2); x>>=1; } return L1.mx[(1<<m)-1][(1<<m)-1];//最后放满,转移到末状态 } int main() { while(scanf("%d%d",&m,&n)==2){ memset(L1.mx,0,sizeof(L1.mx)); dfs(0,0,0); int ans=solve(n-1); printf("%d\n",ans); } return 0; }