首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

HDOJ 5411 CRB and Puzzle:矩陣快速冪計數拼圖模式

     編輯:關於C++

問題建模

有 N 種拼圖塊,第 i 種右側可接的塊集合給定。求長度 ≤ M(≤ 105)的不同拼接模式數,模 2015。空序列也算一種。

矩陣模型

  • 狀態向量 V[i] 表示以第 i 種塊結尾的模式數。
  • 轉移矩陣 A[i][j] = 1 若 i 可接 j,否則 0。
  • 長度 L 的模式數向量 = V0 · AL,其中 V0 = [1, 1, …, 1](長度 1)。
  • 答案 = ΣL=0M Σi (V0 · AL)i。

引入增廣矩陣 B = [A, 0; 1…1, 1],則 BM 的第一行和即為答案。

矩陣快速冪

struct Matrix {
    int a[55][55];
    Matrix operator*(const Matrix &o) const {
        Matrix r; memset(r.a, 0, sizeof(r.a));
        for (int i = 0; i < n; ++i)
            for (int k = 0; k < n; ++k) if (a[i][k])
                for (int j = 0; j < n; ++j)
                    r.a[i][j] = (r.a[i][j] + a[i][k] * o.a[k][j]) % MOD;
        return r;
    }
};
Matrix qpow(Matrix base, long long exp) {
    Matrix res; // 單位矩陣
    for (int i = 0; i < n; ++i) res.a[i][i] = 1;
    while (exp) {
        if (exp & 1) res = res * base;
        base = base * base;
        exp >>= 1;
    }
    return res;
}

完整代碼

#include <bits/stdc++.h>
using namespace std;
const int MOD = 2015, MAXN = 55;
int n; long long m;
struct Matrix {
    int a[MAXN][MAXN];
    Matrix() { memset(a, 0, sizeof(a)); }
    void identity() { for (int i = 0; i < n; ++i) a[i][i] = 1; }
    Matrix operator*(const Matrix &o) const {
        Matrix r;
        for (int i = 0; i < n; ++i)
            for (int k = 0; k < n; ++k) if (a[i][k])
                for (int j = 0; j < n; ++j)
                    r.a[i][j] = (r.a[i][j] + a[i][k] * o.a[k][j]) % MOD;
        return r;
    }
};
int main() {
    int T; scanf("%d", &T);
    while (T--) {
        scanf("%d%lld", &n, &m);
        Matrix A;
        for (int i = 0; i < n; ++i) {
            int k, x; scanf("%d", &k);
            while (k--) { scanf("%d", &x); A.a[i][x - 1] = 1; }
        }
        // 增廣矩陣 B: size n+1
        Matrix B; int sz = n + 1;
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j) B.a[i][j] = A.a[i][j];
        for (int j = 0; j < n; ++j) B.a[n][j] = 1; // 最後一行全 1
        B.a[n][n] = 1; // 保持累加
        Matrix ans = qpow(B, m);
        int sum = 0;
        for (int j = 0; j <= n; ++j) sum = (sum + ans.a[n][j]) % MOD;
        printf("%d\n", sum);
    }
    return 0;
}

複雜度

矩陣乘法 O(N3),冪指數 M ≤ 105,log M ≈ 17,N ≤ 50,總運算量約 503 × 17 ≈ 2×106,極快。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved