矩阵快速幂

Posted lihaozhe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵快速幂相关的知识,希望对你有一定的参考价值。

矩阵

定义

按照一个长方阵列排列的复数或实数集合。

看不懂?那就看图

(A)是一个(n imes m)的矩阵,则(A)可以表示为
[ A_{n, m}=left[egin{array}{ll}A_{1,1}&A_{1,2}&cdots &A_{1,m}\A_{2,1}&A_{2,2}&cdots &A_{2,m}\vdots&vdots&ddots&vdots\A_{n,1}&A_{n,2}&cdots &A_{n,m}end{array} ight] ]

(m imes n)个数成为矩阵(A)的元素,简称为元。数(a_{i, j})位于矩阵(A)的第(i)行第(j)列,称为矩阵(A)((i, j))元。

(m imes n)矩阵可记作矩阵(A)或矩阵(A_{m, n})

若矩阵(A)与矩阵(B)的行数和列数都相同,则称矩阵(A)与矩阵(B)是同型矩阵

实现:

const int N=100;
struct Matrix {
    LL a[N][N]; int n, m;
    Matrix(int type, int n, int m):n(n), m(m) {
        memset(a, 0, sizeof(a));
    }
    void print() {
        for (int i=0; i<n; i++, puts(""))
            for (int j=0; j<m; j++)
                printf("%d ", a[i][j]);
    }
};

运算

加法

减法

数乘

咕咕咕~

乘法

当且仅当矩阵(A)的列数等于矩阵(B)的行数时,(A imes B)有定义

不放设(A)是一个(m imes n)的矩阵,(B)是一个(m imes p)的矩阵,那么(C=A imes B)是一个(n imes p)的矩阵,且(C_{i, j}=sum_{k=1}^mA_{i, k}B_{k, j})

理解:(C)矩阵的((i, j))元就是(A)矩阵中的第(i)行和(B)矩阵的第(j)列每项顺次相乘的和

更形象地理解,即为将(A)矩阵的第(i)行拿出来,顺时针旋转(90^circ)后平移使其与(B)矩阵的第(j)列对齐,将每对对齐的数分别相乘再求和即可。

在后面矩阵快速幂的应用中有例子模拟。

实现:

Matrix operator*(const Matrix &a, const Matrix &b) {
    assert(a.m==b.n);
    Matrix c(0, a.n, b.m);
    for (int i=0; i<a.n; i++)
        for (int j=0; j<b.m; j++)
            for (int k=0; k<a.m; k++)
                c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%P;
    return c;
}

矩阵快速幂

问题

根据矩阵乘法的定义,一个(n imes n)的矩阵显然可以进行幂运算。

要求在(O(log n))时间内求出一个矩阵的(n)次幂

思路

对于整数,我们可以将指数二进制拆分后快速幂。

那么对于矩阵是否可以进行类似的操作呢?

显然可以。

实现矩阵乘法后,运算部分与快速幂无异。

注意快速幂要将答案的初值赋为(1),目的是使(ans imes x=x),避免在乘法时对(ans)讨论。那么是否也存在一个矩阵满足类似的性质呢?

确实存在。

对于任意一个(n imes n)的矩阵(x),存在(n imes n)的单位矩阵(I),满足(I imes x=x)

很容易得到这个矩阵为
[ I=left[egin{array}{ll}1&0&0&cdots&0\0&1&0&cdots&0\0&0&1&cdots&0\vdots&vdots&vdots&ddots&vdots\0&0&0&cdots&1end{array} ight] ]

实现

Matrix qpow(Matrix a, int b) {
    assert(a.n==a.m);
    Matrix ans(1, a.n, a.m);
    for (; b; b>>=1, a=a*a) if (b&1) ans=ans*a;
    return ans;
}

应用

快速转移线性递推式

以洛谷模板题洛谷P1939 【模板】矩阵加速(数列)为例

此题(f_n=f_{n-1}+f_{n-3})

用矩阵改写转移
[ left[egin{array}{ll}f_n\f_{n-1}\f_{n-2}\f_{n-3}end{array} ight]=left[egin{array}{ll}1&0&1&0\1&0&0&0\0&1&0&0\0&0&1&0end{array} ight] imesleft[egin{array}{ll}f_{n-1}\f_{n-2}\f_{n-3}\f_{n-4}end{array} ight] ]
可以验证此矩阵转移式和题中线性递推式等价。

我们上面矩阵乘法讲的trick来验证一下答案矩阵的第一行,即(f_n)

右边第一个矩阵的第一行顺时针旋转(90^circ)并平移使其与和第二个矩阵的第一列对齐
[ left[egin{array}{ll}1\0\1\0end{array} ight]left[egin{array}{ll}f_{n-1}\f_{n-2}\f_{n-3}\f_{n-4}end{array} ight] ]

将每对对齐的数相乘得
[ left[egin{array}{ll}1 imes f_{n-1}\0 imes f_{n-2}\1 imes f_{n-3}\0 imes f_{n-4}end{array} ight] ]
求和,应用递推式得
[ f_{n-1}+f_{n-3}=f_n ]
答案矩阵后三行很容易验证。那么等式成立

将这个等式迭代下去得
[ left[egin{array}{ll}f_n\f_{n-1}\f_{n-2}\f_{n-3}end{array} ight]=left[egin{array}{ll}1&0&1&0\1&0&0&0\0&1&0&0\0&0&1&0end{array} ight]^{n-4} imesleft[egin{array}{ll}f_1\f_2\f_3\f_4end{array} ight] ]

(f_1)(f_4)均已知,那么利用矩阵快速幂即可在(O(log n))时间内求出(f)数列的第(n)

以上是关于矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章

矩阵快速幂

初步 - 矩阵快速幂

poj 3233(矩阵快速幂)

模板之矩阵快速幂(luogu P3390模板矩阵快速幂)

数学问题——矩阵和矩阵快速幂

矩阵快速幂