AcWing 1303. 斐波那契前 n 项和

\(AcWing\) \(1303\). 斐波那契前 \(n\) 项和

一、题目描述

大家都知道 \(Fibonacci\) 数列吧,\(f_1=1,f_2=1,f_3=2,f_4=3,…,f_n=f_{n−1}+f_{n−2}\)

现在问题很简单,输入 \(n\)\(m\),求 \(f_n\) 的前 \(n\) 项和 \(S_n \ mod \ m\)

输入格式
共一行,包含两个整数 \(n\)\(m\)

输出格式
输出前 \(n\) 项和 \(S_n\ mod\ m\) 的值。

数据范围
\(1≤n≤2000000000,1≤m≤1000000010\)

输入样例
\(5\) \(1000\)

输出样例
\(12\)

二、解题思路

普通的迭代法,是线性的,\(n\)的上限是\(2e9\),循环的话会超时,需要想其它办法。

矩阵快速幂

\[\large \begin{bmatrix} s_n & f_{n+1}& f_n \end{bmatrix} \times \begin{bmatrix} a&b &c \\ d&e & f \\ h&i & j \\ \end{bmatrix} = \begin{bmatrix} s_{n+1} & f_{n+2}& f_{n+1} \end{bmatrix}\]

\(\therefore \\ s_{n+1}= s_n \times a+f_{n+1} \times d+f_n \times h \\ f_{n+2}= s_n \times b + f_{n+1} \times e + f_n \times i \\ f_{n+1}= s_n \times c + f_{n+1} \times f + f_n \times j \)

根据题目的现实含义:
\(s_{n+1}=s_n+f_{n+1}\)
\(f_{n+2}=f_n+f_{n+1}\)

推导出:
\(a=1,d=1,h=0\)
\(b=0,e=1,i=1\)
\(c=0,f=1,j=0\)

整理出矩阵就是:
\(m=\begin{bmatrix} 1 & 0 & 0 \\ 1 & 1 & 1 \\ 0 & 1 & 0 \end{bmatrix}\)

已知 \(s_1=1,f_2=1,f_1=1\),使用矩阵快速幂可以求解 \(s_n\)
\(b=\begin{bmatrix} 1 & 1& 1 \end{bmatrix}\)

\(\begin{bmatrix}s_1 & f_2 & f_1 \end{bmatrix} \times \begin{bmatrix} 1 & 0 & 0 \\ 1 & 1 & 1 \\ 0 & 1 & 0 \end{bmatrix} =\begin{bmatrix}s_2 & f_3 & f_2 \end{bmatrix} \)

\(\begin{bmatrix}s_2 & f_3 & f_2 \end{bmatrix} \times \begin{bmatrix} 1 & 0 & 0 \\ 1 & 1 & 1 \\ 0 & 1 & 0 \end{bmatrix} =\begin{bmatrix}s_3 & f_4 & f_3 \end{bmatrix} \)

将 ① 代入 ② 得到:

\(\begin{bmatrix}s_1 & f_2 & f_1 \end{bmatrix} \times \begin{bmatrix} 1 & 0 & 0 \\ 1 & 1 & 1 \\ 0 & 1 & 0 \end{bmatrix}^2 =\begin{bmatrix}s_3 & f_4 & f_3 \end{bmatrix} \)

通过数学归纳法,得:

\(\begin{bmatrix}s_1 & f_2 & f_1 \end{bmatrix} \times \begin{bmatrix} 1 & 0 & 0 \\ 1 & 1 & 1 \\ 0 & 1 & 0 \end{bmatrix}^{n-1} =\begin{bmatrix}s_n & f_{n+1} & f_n \end{bmatrix} \)

三、实现代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int N = 3;
int n, mod;

// 矩阵乘法
void mul(int a[][N], int b[][N], int c[][N]) {
    int t[N][N] = {0};
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++)
            for (int k = 0; k < N; k++)
                t[i][j] = (t[i][j] + (a[i][k] * b[k][j]) % mod) % mod;
    }
    memcpy(c, t, sizeof t);
}

signed main() {
    int b[N][N] = {1, 1, 1};
    int m[N][N] = {
        {1, 0, 0},
        {1, 1, 1},
        {0, 1, 0}};

    cin >> n >> mod;

    for (int i = n - 1; i; i >>= 1) {
        if (i & 1) mul(b, m, b);
        mul(m, m, m);
    }
    printf("%d\n", b[0][0]);
}
posted @ 2022-06-04 15:28  糖豆爸爸  阅读(105)  评论(0编辑  收藏  举报
Live2D