TonyYin's Blog

Back

题目地址:P1962 斐波那契数列 - 洛谷 | 计算机科学教育新生态

前置知识点

矩阵

定义:

一个n×mn\times m矩阵是由n×mn\times m个实数排列成nnmm列构成的,用一对[]括起来。

下面3×33\times 3矩阵简记为A=(aij)3×3A=(a_{ij})_{3\times 3}

A=[a11a12a13a21a22a23a31a32a33]A=\left[ \begin{matrix} a_{11} & a_{12} & a_{13}\\ a_{21} & a_{22} & a_{23}\\ a_{31} & a_{32} & a_{33}\\ \end{matrix} \right]

矩阵加减

nnmm列矩阵A,BA,B加减规则:A±B=(aij±bij)n×mA\pm B=(a_{ij}\pm b_{ij})_{n\times m}

矩阵加减满足交换律,结合律

A±B=[a11a12a1ma21a22a2man1an2anm]±[b11b12b1mb21b22b2mbn1bn2bnm]=[a11±b11a12±b12a1m±b1ma21±b21a22±b22a2m±b2man1±bn1an2±bn2anm±bnm]\begin{aligned} A\pm B&= \left[\begin{matrix} a_{11}&a_{12}&\cdots&a_{1m}\\ a_{21}&a_{22}&\cdots&a_{2m}\\ \cdots&\cdots&\cdots&\cdots\\ a_{n1}&a_{n2}&\cdots&a_{nm}\\ \end{matrix}\right]\pm \left[\begin{matrix} b_{11}&b_{12}&\cdots&b_{1m}\\ b_{21}&b_{22}&\cdots&b_{2m}\\ \cdots&\cdots&\cdots&\cdots\\ b_{n1}&b_{n2}&\cdots&b_{nm}\\ \end{matrix}\right]\\&= \left[\begin{matrix} a_{11}\pm b_{11}&a_{12}\pm b_{12}&\cdots&a_{1m}\pm b_{1m}\\ a_{21}\pm b_{21}&a_{22}\pm b_{22}&\cdots&a_{2m}\pm b_{2m}\\ \cdots&\cdots&\cdots&\cdots\\ a_{n1}\pm b_{n1}&a_{n2}\pm b_{n2}&\cdots&a_{nm}\pm b_{nm}\\ \end{matrix}\right] \end{aligned}

矩阵乘法

**1.数和矩阵相乘

kA=Ak=[ka11ka12ka1mka21ka22ka2mkan1kan2kanm] kA=Ak= \left[\begin{matrix} ka_{11}&ka_{12}&\cdots&ka{1m}\\ ka_{21}&ka_{22}&\cdots&ka{2m}\\ \cdots&\cdots&\cdots&\cdots\\ ka_{n1}&ka_{n2}&\cdots&ka{nm}\\ \end{matrix}\right]

2.矩阵和矩阵相乘

原理:Cij=AC_{ij}=A的第ii行和BB的第jj列每个元素对应相乘的和。

所以矩阵乘法当且仅当A的列数=B的行数时才有定义。

由于矩阵乘法的规则,ABBAA\cdot B\not= B\cdot A

具体方法:Cij=ai1b1j+ai2b2j++aitbtj=r=1tairbrj\textcolor{red}{C_{ij}}=a_{i1}b_{1j}+a_{i2}b_{2j}+\cdots+a_{it}b_{tj}=\textcolor{red}{\sum_{r=1}^{t}a_{ir}b_{rj}}

实现

struct matrix {
   int n, m;
   int a[100][100];
};
// A.m == B.n
matrix matrix_mul(matrix A, matrix B) {
    matrix C;
    C.n = A.n;
    C.m = B.m;
    for (int i = 0; i < A.n; ++i) {
        for (int j = 0; j < B.m; ++j) {
            C.a[i][j] = 0;
            for (int k = 0; k < A.m; ++k) {
                C.a[i][j] += A.a[i][k] * B.a[k][j];
            }
        }
    }
    return C;
}
cpp

单位矩阵

形如:

[1000100001]\left[\begin{matrix} 1&0&\cdots&0\\ 0&1&\cdots&0\\ \cdots&\cdots&\cdots&\cdots\\ 0&0&0&1\\ \end{matrix}\right]

主对角线上元素均为1,其余元素均为0的矩阵。通常记做InI_nEnE_n

性质:

AIn=AA\cdot I_n=A

InA=AI_n\cdot A=A

即任何一个矩阵左乘或右乘单位矩阵,结果不变(相当于乘法当中的 11

矩阵快速幂

快速幂

int quick_power(int x,int y){
    int ans = 1,cnt = x;
    while(y){
        if(y & 1){
           ans *= cnt;
        }
        cnt *= cnt;
        y >>= 1;
    }
   return ans;
}
cpp

矩阵快速幂

利用快速幂思想,快速求矩阵AnA^n

将快速幂中的乘法替换为矩阵乘法,参数和返回值替换为矩阵即可。

int n; // 所有矩阵都是 n * n 的矩阵
struct matrix {
   int a[100][100];
};
matrix matrix_mul(matrix A, matrix B, int mod) {
    // 2 个矩阵相乘
    matrix C;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            C.a[i][j] = 0;
            for (int k = 0; k < n; ++k) {
                C.a[i][j] = (C.a[i][j] + A.a[i][k] * B.a[k][j] % mod) % mod;
            }
        }
    }
    return C;
}
matrix unit() {
    // 返回一个单位矩阵
    matrix res;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) {
                res.a[i][j] = 1;
            } else {
                res.a[i][j] = 0;
            }
        }
    }
    return res;
}
matrix matrix_pow(matrix A, int p, int mod) {
    // 快速求矩阵 A 的 p 次方
    matrix res = unit();
    while (p > 0) {
        if (p & 1) {
            res = matrix_mul(res, A, mod);
        }
        A = matrix_mul(A, A, mod);
        p >>= 1;
    }
    return res;
}
cpp

本题题解

斐波那契数列递推式:

an=an1+an2a_n=a_{n-1}+a_{n-2}

Ai=[ai,ai+1]A_i=\left[\begin{matrix}a_i,a_{i+1}\end{matrix}\right]

先构造1×21\times 2的矩阵A1=[a1,a2]A_1=\left[\begin{matrix}a_1,a_2\end{matrix}\right],考虑构造矩阵 BB 使得 A1×B=A2A_1\times B=A_2

通过观察推导得到B=[0111]B=\left[\begin{matrix}0&1\\1&1\end{matrix}\right]

A2=A1×BA3=A2×B=A1×B×B=A1×B2\begin{aligned} &\therefore A_2=A_1\times B\\ &\therefore A_3=A_2\times B=A_1\times B\times B=A_1\times B^2 \end{aligned} \cdots Ai=A1×Bi1=[1,1]×[0111]i1A_i=A_1\times B^{i-1}= \left[\begin{matrix}1,1\end{matrix}\right] \times \left[\begin{matrix} 0&1\\ 1&1\\ \end{matrix}\right]^{i-1}

时间复杂度O(logN)\mathcal{O}(\log N)

【洛谷-P1962】斐波那契数列
https://www.tonyyin.top/blog/oi-solution/p1962
Author TonyYin
Published at December 30, 2020
What do you think?
  • Like
    0
    Like
Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v3.4.1