AcWing 1303:斐波那契前 n 项和 ← 矩阵快速幂加速递推

【题目来源】
https://www.acwing.com/problem/content/1305/
http://poj.org/problem?id=3070

【题目描述】
大家都知道 Fibonacci 数列吧,F_1=1,F_2=1,F_3=2,F_4=3,\cdots ,F_n=F_{n-1}+F_{n-2}。现在问题很简单,输入 nm,求 F_n 的前 n 项和 S_n \, mod \, m

【输入格式】
共一行,包含两个整数 nm

【输出格式】
输出前 n 项和 S_n \, mod \, m 的值。

【数据范围】
1\leq n \leq 2000000000,\\ 1 \leq m \leq1000000010

【输入样例】
5 1000

【输出样例】
12

【算法分析】
★ 矩阵快速幂加速递推
(1)已知 Fibonacci 数列递推式为 F_n=F_{n-1}+F_{n-2},但当 n 极大时,会超时。
故基于“
矩阵快速幂加速递推”的思路,改写数列递推式 F_n=F_{n-1}+F_{n-2} 为 [F_n \quad F_{n-1}]=[F_{n-1} \quad F_{n-2}] \begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix} =[F_{n-2} \quad F_{n-3}] \begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix} \begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix} =\cdots =[F_1,F_0] \begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix}^{n-1}
改写后的递推式对应的 LaTex 代码为:

[F_n \quad F_{n-1}]=[F_{n-1} \quad F_{n-2}] 
\begin{bmatrix}
1 & 1\\ 
1 & 0
\end{bmatrix}
=[F_{n-2} \quad F_{n-3}] 
\begin{bmatrix}
1 & 1\\ 
1 & 0
\end{bmatrix} 
\begin{bmatrix}
1 & 1\\ 
1 & 0
\end{bmatrix}
=\cdots =[F_1,F_0]
\begin{bmatrix}
1 & 1\\ 
1 & 0
\end{bmatrix}^{n-1}

(2)若令 X_n=[F_n \quad F_{n-1}], \, X_1=[F_1 \quad F_0], \, A=\begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix},则有 \textcolor{red} {X_n=X_1\times A^{n-1} }
据此公式可知,首先求出 A^{n-1} \, mod \, p,然后用 X_1 左乘,便可得到 X_n,而 X_n 的第一个元素即为 F_n注意:标红的公式,技巧在于使用了 LaTex 命令: 
\textcolor{red} { 公式}

\textcolor{red} {X_n=X_1\times A^{n-1}}

★ 矩阵快速幂模板:https://blog.csdn.net/hnjzsyjyj/ar左乘ticle/details/143227091

★ 针对本题而言,可构造矩阵递推式:\textcolor{red} { [F_{n+1} \quad F_n \quad S_n] \begin{bmatrix} 1 & 1 & 1\\ 1 & 0 & 0\\ 0 & 0 & 1 \end{bmatrix} =[F_{n+2} \quad F_{n+1} \quad S_{n+1}] }
此公式未设红色的 LaTex 代码如下所示:

[F_{n+1} \quad F_n \quad S_n] 
\begin{bmatrix}
1 & 1 & 1\\ 
1 & 0 & 0\\ 
0 & 0 & 1
\end{bmatrix}
=[F_{n+2} \quad F_{n+1} \quad S_{n+1}]

根据此递推式,可得通项式为:\textcolor{red}{ [F_1 \quad F_0 \quad S_0] \begin{bmatrix} 1 & 1 & 1\\ 1 & 0 & 0\\ 0 & 0 & 1 \end{bmatrix}^n =[F_{n+1} \quad F_n \quad S_n] }
此递推式对应的未设红色的 LaTex 代码如下所示:

[F_1 \quad F_0 \quad S_0] 
\begin{bmatrix}
1 & 1 & 1\\ 
1 & 0 & 0\\ 
0 & 0 & 1
\end{bmatrix}^n
=[F_{n+1} \quad F_n \quad S_n]

接下来,便可以在 O(logn) 的时间复杂度下,用矩阵快速幂计算出 \begin{bmatrix} 1 & 1 & 1\\ 1 & 0 & 0\\ 0 & 0 & 1 \end{bmatrix}^n
 
【算法代码】

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N=3;
int n,m;

void mul(int a[][3],int b[][3],int c[][3]) {
    int t[3][3];
    memset(t,0,sizeof t);

    for(int i=0; i<3; i++)
        for(int j=0; j<3; j++)
            for(int k=0; k<3; k++)
                t[i][j]=(t[i][j]+(LL)a[i][k]*b[k][j]%m)%m;

    memcpy(c,t,sizeof t);
}

int main() {
    int a[N][N]= {
        {1,0,0},
        {0,0,0},
        {0,0,0}
    };

    int b[N][N]= {
        {1,1,1},
        {1,0,0},
        {0,0,1}
    };

    cin>>n>>m;
    while(n) { //fastPow
        if(n & 1) mul(a,b,a);
        mul(b,b,b);
        n>>=1;
    }
    cout<<a[0][2]<<endl;

    return 0;
}

/*
in:
5 1000

out:
12
*/





【参考文献】
https://blog.csdn.net/qq_46105170/article/details/131256062
https://www.acwing.com/solution/content/47987/
https://www.cnblogs.com/lipoicyclic/p/14994631.html
https://www.cnblogs.com/littlehb/p/16341964.html
https://www.acwing.com/blog/content/25/
https://blog.csdn.net/hnjzsyjyj/article/details/143227091
https://www.cnblogs.com/yijiull/p/6641422.html

https://www.acwing.com/solution/content/15121/

 

猜你喜欢

转载自blog.csdn.net/hnjzsyjyj/article/details/143352015