Loading

Power of Matrix

思路

书上的原题, 早就会了

听了一下 \(\rm{WGC}\) 大佬讲题, 这篇权当记录一下, 并且熟练一下矩阵 \(\LaTeX\) 的写法

首先我们发现, 直接往上加是慢的, 我们考虑先转化一下

\(s_i = A^0 + A^1 + A^2 + \cdots A^i\)

那么有, \(s_i = s_{i - 1} + A^i\)

考虑用这个来矩阵优化

容易想到设计矩阵

\[\begin{pmatrix} s_i \\ A^i \end{pmatrix} \]

那么如何转移

显然的

\[\begin{pmatrix} s_i \\ A^i \end{pmatrix} \cdot \begin{pmatrix} I & I \\ 0 & A \end{pmatrix} = \begin{pmatrix} s_{i + 1} \\ A^{i + 1} \end{pmatrix} \]

直接做就好了

不是哥们, 思路错了

实际上我们需要把矩阵扔进去, 而非直接用矩阵套矩阵来处理

实现

框架

以这个题, 确定我矩阵的基本模板

实现

#include <bits/stdc++.h>
#define int long long
const int MAXN = 300;
const int MOD = 10;

int N, K, i, j;
struct Matrix
{
    int M[MAXN][MAXN];
    void clear() { memset(M, 0, sizeof(M)); }
    void reset() {
        clear();
        for (int i = 1; i <= N; ++i)
            M[i][i] = 1;
    }
    Matrix friend operator * (const Matrix &A, const Matrix &B) {
        Matrix Ans;
        Ans.clear();
        for (int i = 1; i <= N; ++i)
            for (int k = 1; k <= N; ++k)
                for (int j = 1; j <= N; ++j)
                    Ans.M[i][j] = (Ans.M[i][j] + A.M[i][k] * B.M[k][j]) % MOD;
        return Ans;
    }
    Matrix friend operator + (const Matrix &A, const Matrix &B) {
        Matrix Ans;
        Ans.clear();
        for (int i = 1; i <= N; ++i)
            for (int j = 1; j <= N; ++j)
                Ans.M[i][j] = (A.M[i][j] + B.M[i][j]) % MOD;
        return Ans;
    }
} base, ans;

inline Matrix matrix_quickpow(Matrix T, int P)
{
    Matrix Ans;
    Ans.reset();
    while (P)
    {
        if (P & 1)
            Ans = Ans * T;
        T = T * T;
        P >>= 1;
    }
    return Ans;
}

signed main()
{
    while (scanf("%lld %lld", &N, &K) && N && K)
    {
        base.clear(), ans.clear();
        for (i = 1; i <= N; ++i) {
            for (j = 1; j <= N; ++j)
                scanf("%lld", &base.M[i][j]);
            base.M[N + i][i] = base.M[N + i][N + i] = 1;
        }
        N <<= 1;
        ans = matrix_quickpow(base, K + 1);
        N >>= 1;
        for (i = 1; i <= N; ++i)
            for (j = 1; j <= N; ++j) {
                int Out = ans.M[N + i][j] % MOD;
                if (i == j)
                    Out = (Out + MOD - 1) % MOD;
                printf("%lld", Out);
                if (j == N) printf("\n");
                else printf(" ");
            }
        printf("\n");
    }
    return 0;
}

总结

善于推导递推

矩阵的的特殊实现, 仅仅只需要把东西扔进去

posted @ 2024-12-18 20:10  Yorg  阅读(36)  评论(0)    收藏  举报