矩阵快速幂

简介 #

矩阵快速幂能将 $O(n)$ 的线性递推优化成 $O(\log n)$.

矩阵 #

矩阵相当于二维数组.

  • 矩阵 $A$ 有 $m$ 行 $n$ 列,称为 $m×n$ 矩阵,简记为 $A_{mn}$.

  • 矩阵 $A$ 第 $i$ 行 $j$ 列的元素写作 $a_{ij}$.

$$A=\begin{bmatrix} a_{11}& a_{12}& \cdots & a_{1n}\\ a_{21}& a_{22}& \cdots & a_{2n}\\ \vdots & \vdots & \ddots & \vdots \\ a_{m1}& a_{m2}& \cdots & a_{mn} \end{bmatrix}$$

单位矩阵 #

主对角线上的元素都为 $1$,其余元素为 $0$ 的 $n×n$ 矩阵称为 $n$ 阶单位矩阵,记作 $I_n$ 或 $E_n$.

$$I_n=\begin{bmatrix} 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{bmatrix}$$

矩阵加、减法 #

矩阵的加减法就是将两个矩阵对应位置上的元素相加减.

$$C_{ij}=A_{ij}±B_{ij}$$

矩阵乘法 #

定义矩阵 $A×B=C$:

  • 必须满足 $A$ 的列数 $=$ $B$ 的行数.

  • $A_{mr}×B_{rn}$ 会得到一个 $m×n$ 矩阵.

$$C_{ij}=\sum_{k=1}^nA_{ik}\cdot B_{kj}$$

任意矩阵乘 $I_n$ 都等于它本身.

  • 矩阵乘法满足结合律,不满足交换律.

  • 只有行数 $=$ 列数的矩阵才能进行乘幂运算.

矩阵快速幂 #

基于 快速幂 的思想求 $n$ 阶矩阵的 $x$ 次方. 时间复杂度:$O(n^3\log x)$.

矩阵运算可能需要高精度或取模.

const int N = 101; // 矩阵的行数和列数

struct matrix {
    int at[N][N];
    matrix() { memset(at, 0, sizeof at); }
    int* operator[](int key) { return at[key]; }
};

matrix operator *(matrix a, matrix b) { // 矩阵 A × 矩阵 B
    matrix c;
    for (int i = 0; i < N; i ++)
        for (int j = 0; j < N; j ++)
            for (int k = 0; k < N; k ++)
                c[i][j] += a[i][k] * b[k][j];
    return c;
}

matrix operator ^(matrix a, int x) {    // 矩阵 A 的 x 次方
    matrix res;
    for (int i = 0; i < N; i ++)        // 初始化为单位矩阵
        res[i][i] = 1;
    while(x) {
        if(x % 2) res = res * a;
        a = a * a, x /= 2;
    }
    return res;
}

应用 #

若已知 $f(1),f(2)$,且有矩阵 $A$ 满足

$$A\times \begin{bmatrix} f(n)\\ f(n-1) \end{bmatrix} = \begin{bmatrix} f(n+1)\\ f(n) \end{bmatrix}$$

就可推出 $f(n)$ 的值.

$$(A^{n-2})\times \begin{bmatrix} f(2)\\ f(1) \end{bmatrix} = \begin{bmatrix} f(n)\\ f(n-1) \end{bmatrix}$$

可用矩阵快速幂求 $A^{n-2}$. 时间复杂度:$O(\log n)$.

例 1 #

求斐波那契数列的第 $n$ 项 $f(n)$($n\geq 10^{12}$).

$$f(n)= \begin{cases} 1&n=1,2\\ f(n-1)+f(n-2)&n\geq 3 \end{cases}$$

设矩阵 $A=\begin{bmatrix}a_{11}&a_{12}\newline a_{21}&a_{22}\end{bmatrix}$ 满足

$$\begin{bmatrix} a_{11}&a_{12}\\ a_{21}&a_{22} \end{bmatrix} \times \begin{bmatrix} f(n)\\ f(n-1) \end{bmatrix} = \begin{bmatrix} f(n+1)\\ f(n) \end{bmatrix}$$

$$\begin{cases} f(n+1)&=&a_{11}\cdot f(n)+a_{12}\cdot f(n-1)\\ f(n)&=&a_{21}\cdot f(n)+a_{22}\cdot f(n-1) \end{cases}$$

解得

$$\begin{cases} a_{11}=1&a_{12}=1\\ a_{21}=1&a_{22}=0 \end{cases} , \quad A= \begin{bmatrix} 1&1\\ 1&0 \end{bmatrix}$$

因此

$$\begin{bmatrix} 1&1\\ 1&0 \end{bmatrix} ^{n-2} \times \begin{bmatrix} f(2)\\ f(1) \end{bmatrix} = \begin{bmatrix} f(n)\\ f(n-1) \end{bmatrix}$$

将 $f(1)=f(2)=1$ 代入即可.

int main() {
    matrix A;
    A[1][1] = 1, A[1][2] = 1;
    A[2][1] = 1, A[2][2] = 0;

    matrix B;
    B[1][1]	= 1;	// f(1) = 1
    B[2][1] = 1;	// f(2) = 1

    cin >> n;
    B = (A ^ (n - 2)) * B;
    cout << B[1][1];
}

例 2 #

求数列的第 $n$ 项 $f(n)$($n\geq 10^{12}$).

$$f(n)= \begin{cases} 1&n=1,2\\ f(n-1)+f(n-2)+n-1&n\geq 3 \end{cases}$$

设 $4$ 阶矩阵 $A$ 满足

$$\begin{bmatrix} a_{11}&a_{12}&a_{13}&a_{14}\\ a_{21}&a_{22}&a_{23}&a_{24}\\ a_{31}&a_{32}&a_{33}&a_{34}\\ a_{41}&a_{42}&a_{43}&a_{44} \end{bmatrix} \times \begin{bmatrix} f(n)\\ f(n-1)\\ n\\ 1 \end{bmatrix} = \begin{bmatrix} f(n+1)\\ f(n)\\ n+1\\ 1 \end{bmatrix}$$

解得

$$A= \begin{bmatrix} 1&1&1&0\\ 1&0&0&0\\ 0&0&1&1\\ 0&0&0&1 \end{bmatrix}$$