P1962 斐波那契数列


题目传送门

一、矩阵分析

\[\begin{bmatrix} F(n)\\ F(n-1) \end{bmatrix} =\begin{bmatrix} F(n-1)+F(n-2)\\ F(n-1) \end{bmatrix}=\begin{bmatrix} F(n-1) * 1 + F(n-2)*1\\ F(n-1) * 1 + F(n-2) * 0 \end{bmatrix}=\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\begin{bmatrix} F[n-1]\\ F[n-2] \end{bmatrix} \]

\[\begin{bmatrix} F(n)\\ F(n-1) \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\begin{bmatrix} F(n-1)\\ F(n-2) \end{bmatrix} \\ \begin{bmatrix} F(n-1)\\ F(n-2) \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\begin{bmatrix} F(n-2)\\ F(n-3) \end{bmatrix} \\ \begin{bmatrix} F(n)\\ F(n-1) \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^2\begin{bmatrix} F(n-2)\\ F(n-3) \end{bmatrix}\]

以此类推

\[\begin{bmatrix} F(n)\\ F(n-1) \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^{n-2}\begin{bmatrix} F(2)\\ F(1) \end{bmatrix} \]

所以要求斐波那契的第\(n\)项,我们只需要求得\(F(2)\)\(F(1)\)构成的矩阵与特定矩阵的\(n-2\)次方相乘后的矩阵,然后取该矩阵的第一行第一列的元素值就是\(F(n)\)

二、实现代码I

#include 
using namespace std;
typedef long long LL;
const int N = 10;
const int MOD = 1e9 + 7;

//矩阵声明
struct JZ {
    LL m[N][N];
} res, base;

inline JZ mul(JZ A, JZ B) {
    JZ C;
    memset(C.m, 0, sizeof(C.m));
    for (int i = 1; i <= 2; i++)
        for (int j = 1; j <= 2; j++)
            for (int k = 1; k <= 2; k++) {
                C.m[i][j] = (C.m[i][j] + (A.m[i][k] * B.m[k][j]) % MOD) % MOD;
            }
    return C;
}

//快速幂
inline void qmi(LL k) {
    memset(res.m, 0, sizeof res.m);
    res.m[1][1] = res.m[1][2] = 1; // f(1)=1,f(2)=1 乘一次矩阵就是f(3),所以f(n)就是n-2次方
    while (k) {
        if (k & 1) res = mul(res, base);
        base = mul(base, base);
        k >>= 1;
    }
}
int main() {
    LL n;
    cin >> n;
    if (n <= 2) {
        puts("1");
        return 0;
    }
    //结果矩阵初始化
    memset(base.m, 0, sizeof base.m);
    base.m[1][1] = base.m[1][2] = base.m[2][1] = 1;
    /*
    1 1
    1 0
    base 矩阵
    */
    //快速幂
    qmi(n - 2);
    //结果
    cout << (res.m[1][1]) % MOD << endl;
    return 0;
}


三、实现代码II

#include 
using namespace std;
typedef long long LL;
const int N = 10;
const int MOD = 1e9 + 7;

LL base[N][N], res[N][N];

inline void mul(LL C[][N], LL A[][N], LL B[][N]) {
    static LL tmp[N][N];
    memset(tmp, 0, sizeof(tmp));
    for (int i = 1; i <= 2; i++)
        for (int j = 1; j <= 2; j++)
            for (int k = 1; k <= 2; k++)
                tmp[i][j] = (tmp[i][j] + (A[i][k] * B[k][j]) % MOD) % MOD;
    memcpy(C, tmp, sizeof tmp);
}

//快速幂
inline void qmi(LL k) {
    //初始化结果数组的(i,i)=1
    memset(res, 0, sizeof res);
    res[1][1] = res[1][2] = 1;
    while (k) {
        if (k & 1) mul(res, res, base);
        mul(base, base, base);
        k >>= 1;
    }
}

int main() {
    LL n;
    cin >> n;
    if (n <= 2) {
        puts("1");
        return 0;
    }
    //结果矩阵初始化
    memset(base, 0, sizeof base);
    base[1][1] = base[1][2] = base[2][1] = 1;
    //快速幂
    qmi(n - 2);
    //结果
    cout << (res[1][1]) % MOD << endl;
    return 0;
}