用1 x 2的多米諾骨牌填滿M x N矩形的方案數(完美覆蓋)

題意

用 $1 \times 2$ 的多米諾骨牌填滿 $M \times N$ 的矩形有多少種方案,$M \leq 5,N < 2^{31}$,輸出答案模 $p$.spa

分析

當 $M=3$時,假設前 $n-2$列已經填滿,$n-1$ 列不全,現要向左推動一列。.net

 每列只有8種狀況,若是一種狀況能轉移到另外一種則連一條邊。code

答案就是從「111」出發剛好走 $n$ 步又回到「111」 的路徑數,這個問題等價於求轉移矩陣的 $n$ 次方.blog

肯定轉移矩陣,使用矩陣快速冪,$mat[7][7]$ 就是答案。get

實現

$M=3$ 時,string

#include<cstdio> #include<cstring>
using namespace std; typedef long long ll; struct matrix { int r, c; ll mat[8][8]; matrix(){ memset(mat, 0, sizeof(mat)); } }; const ll p = 1e9+7; int n, m=3; matrix mul(matrix A, matrix B) //矩陣相乘
{ matrix ret; ret.r = A.r; ret.c = B.c; for(int i = 0;i < A.r;i++) for(int k = 0;k < A.c;k++) for(int j = 0;j < B.c;j++) { ret.mat[i][j] = (ret.mat[i][j] + A.mat[i][k] * B.mat[k][j])%p; } return ret; } matrix mpow(matrix A, int n) { matrix ret; ret.r = A.r; ret.c = A.c; for(int i = 0;i < ret.r;i++)  ret.mat[i][i] = 1; while(n) { if(n & 1)  ret = mul(ret, A); A = mul(A, A); n >>= 1; } return ret; } int main() { scanf("%d", &n); matrix A; A.r = A.c = 8; A.mat[0][7] = A.mat[1][6] = A.mat[2][5] = A.mat[3][4] = A.mat[3][7] = A.mat[4][3] = A.mat[5][2] = A.mat[6][1] = A.mat[6][7] = A.mat[7][0] = A.mat[7][3] = A.mat[7][6] = 1; A = mpow(A, n); printf("%lld\n", A.mat[7][7]); }

 

 

參考連接:io

1. http://www.matrix67.com/blog/archives/276class

2. https://blog.csdn.net/starcuan/article/details/19076095im

3. https://blog.csdn.net/heyuchang666/article/details/68067962d3

相關文章
相關標籤/搜索