码迷,mamicode.com
首页 > 其他好文 > 详细

矩阵快速幂

时间:2019-10-28 21:11:55      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:存在   sse   元素   toc   a*   operator   目的   线性   play   

矩阵

定义

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

看不懂?那就看图

\(A\)是一个\(n \times m\)的矩阵,则\(A\)可以表示为
\[ A_{n, m}=\left[\begin{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}\right] \]

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

\(m\times 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\times B\)有定义

不放设\(A\)是一个\(m\times n\)的矩阵,\(B\)是一个\(m\times p\)的矩阵,那么\(C=A\times B\)是一个\(n\times 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\times n\)的矩阵显然可以进行幂运算。

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

思路

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

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

显然可以。

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

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

确实存在。

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

很容易得到这个矩阵为
\[ I=\left[\begin{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&1\end{array}\right] \]

实现

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[\begin{array}{ll}f_n\\f_{n-1}\\f_{n-2}\\f_{n-3}\end{array}\right]=\left[\begin{array}{ll}1&0&1&0\\1&0&0&0\\0&1&0&0\\0&0&1&0\end{array}\right]\times\left[\begin{array}{ll}f_{n-1}\\f_{n-2}\\f_{n-3}\\f_{n-4}\end{array}\right] \]
可以验证此矩阵转移式和题中线性递推式等价。

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

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

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

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

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

矩阵快速幂

标签:存在   sse   元素   toc   a*   operator   目的   线性   play   

原文地址:https://www.cnblogs.com/LiHaozhe/p/11755059.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!