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


題意

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

分析

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

 每列只有8種情況,如果一種情況能轉移到另一種則連一條邊。

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

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

實現

$M=3$ 時,

#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]);
}

 

 

參考鏈接:

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

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM