矩阵快速幂

1.参考

参考: 【矩阵快速幂】简单题学「矩阵快速幂」

2.定义

2.1 定义



如果直接求取 M^n,时间复杂度是 O(n),可以定义矩阵乘法,然后用快速幂算法来加速这里 M^n的求取, 简化时间复杂度为 O(logn)
主体思路就是不求 M^n 而是求 M^(n/2), 然后先不求M^(n/2), 先求M^(n/4)

具体实现同样可以用二进制分解加位掩码来实现(具体可以参考快速幂),只是当某个位掩码为 1 表示该位需要的时候,做的是快速幂做的是乘法,矩阵快速幂做的是矩阵乘法。
实现矩阵快速幂,可以先写一个 struct Matrix 表示矩阵,之后的乘法,求幂都是针对这个类的运算。
其中用一个二维数组做数据成员,一个 init () 方法,将矩阵初始化为单位阵 \(\begin{bmatrix}1&0\\0&1\end{bmatrix}\)。然后重载 * 和 ^ 分别表示矩阵乘法和矩阵快速幂。代码如下:
其中 M 表示方阵的行数。

2.2 代码模板

代码模板1

using ll = long long;
const int M = 2;

struct Ma
{
    int a[M][M]; // 存取矩阵值
    Ma()
    {
        memset(a, 0, sizeof(a));
    }

    void init() // 初始化单位矩阵
    {
        a[0][0] = a[1][1] = 1;
        a[0][1] = a[1][1] = 0;
    }

    Ma operator*(const Ma& B) const // 矩阵乘法(结果固定为一个2*2的矩阵)
    {
        Ma ans;
        for(int i = 0; i < M; ++i)
            for(int j = 0; j < M; ++j)
                for(int k = 0; k < M; ++k)
                    ans.a[i][j] += a[i][k] * B.a[k][j];
        return ans;
    }

    Ma operator^(int n) const // 矩阵幂
    {
        Ma ans;
        ans.init(); // 初始化一个单位矩阵
        Ma A = *this; // 拷贝一个出来用于自乘
        while(n)
        {
            if(n & 1)
                ans = ans * A;
            A = A * A;
            n >>= 1;
        }
        return ans;
    }
};

3.例题

3.1 LCR 126. 斐波那契数

链接LCR 126. 斐波那契数
这个模板不如上面那个通用,更多是针对本题的,可以学习参考

代码模板

    vector<vector<long>> pow(vector<vector<long>>& a, int n) { // 矩阵幂
        vector<vector<long>> ret{{1, 0}, {0, 1}};
        while (n > 0) {
            if (n & 1) { // 使用二进制分解的方法, 进行矩阵快速幂运算
                ret = multiply(ret, a);
            }
            n >>= 1;
            a = multiply(a, a); // 平方自增
        }
        return ret;
    }

    vector<vector<long>> multiply(vector<vector<long>>& a, vector<vector<long>>& b) { // 矩阵乘法
        vector<vector<long>> c{{0, 0}, {0, 0}};
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                c[i][j] = (a[i][0] * b[0][j] + a[i][1] * b[1][j]) % MOD; // 这里因为提前知道是一个2*2矩阵 乘 一个2*2矩阵 = 一个2*2矩阵
            }
        }
        return c;
    }
posted @ 2024-04-26 18:59  DawnTraveler  阅读(12)  评论(0编辑  收藏  举报