#jZCybttg060503. 1643:【例 3】Fibonacci 前 n 项和

1643:【例 3】Fibonacci 前 n 项和

1643:【例 3】Fibonacci 前 n 项和

题目描述

大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,,fn=fn1+fn2f_1=1,f_2=1,f_3=2,f_4=3,\dots ,f_n=f_{n-1}+f_{n-2}

现在问题很简单,输入 nnmm,求 {fn}\{f_n\} 的前 nn 项和 SnmodmS_n \bmod m

输入格式

输入 n,mn, m

输出格式

输出前 nn 项和 SnmodmS_n \bmod m

样例

样例输入 #1

5 1000

样例输出 #1

12

样例解释 #1

Fibonacci 数列前 55 项:1,1,2,3,51,1,2,3,5,和 S5=1+1+2+3+5=12S_5 = 1+1+2+3+5 = 12

12mod1000=1212 \bmod 1000 = 12

数据范围

对于 100%100\% 的数据:

  • 1n2×1091 \le n \le 2 \times 10^9
  • 1m109+101 \le m \le 10^9 + 10

时空限制

  • 时间限制:1000 ms
  • 内存限制:524288 KB

注意nn 很大,不能直接求和。需要利用矩阵快速幂加速。

我们知道 Fibonacci 数列的递推关系:fn=fn1+fn2f_n = f_{n-1} + f_{n-2}。前 nn 项和 Sn=f1+f2++fnS_n = f_1 + f_2 + \dots + f_n。也有递推关系:Sn=Sn1+fnS_n = S_{n-1} + f_n,但这样仍然需要递推。

更好的方法是将 SnS_n 也纳入状态向量。考虑状态向量:

$$\mathbf{F}_n = \begin{bmatrix} f_{n+1} \\ f_n \\ S_n \end{bmatrix}$$

我们希望找到转移矩阵 AA,使得 Fn=AFn1\mathbf{F}_n = A \cdot \mathbf{F}_{n-1}

已知:

  • fn+1=fn+fn1f_{n+1} = f_n + f_{n-1}
  • fn=fnf_n = f_n
  • Sn=Sn1+fnS_n = S_{n-1} + f_n

但 $\mathbf{F}_{n-1} = \begin{bmatrix} f_n \\ f_{n-1} \\ S_{n-1} \end{bmatrix}$,我们需要用 fn,fn1,Sn1f_n, f_{n-1}, S_{n-1} 表示 fn+1,fn,Snf_{n+1}, f_n, S_n

  • $f_{n+1} = 1 \cdot f_n + 1 \cdot f_{n-1} + 0 \cdot S_{n-1}$
  • $f_n = 1 \cdot f_n + 0 \cdot f_{n-1} + 0 \cdot S_{n-1}$
  • $S_n = 1 \cdot f_n + 0 \cdot f_{n-1} + 1 \cdot S_{n-1}$

所以转移矩阵为:

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

验证:Fn=AFn1\mathbf{F}_n = A \cdot \mathbf{F}_{n-1}

初始状态 $\mathbf{F}_1 = \begin{bmatrix} f_2 \\ f_1 \\ S_1 \end{bmatrix} = \begin{bmatrix} 1 \\ 1 \\ 1 \end{bmatrix}$。

那么 Fn=An1F1\mathbf{F}_n = A^{n-1} \cdot \mathbf{F}_1。我们需要的是 SnS_n,即 Fn\mathbf{F}_n 的第三个分量。

因此,算法步骤:

  1. 构造 3×33 \times 3 矩阵 AA 和初始向量 F1F_1
  2. 计算 An1A^{n-1}(用矩阵快速幂)。
  3. 计算 Fn=An1F1\mathbf{F}_n = A^{n-1} \cdot F_1
  4. 输出 Fn\mathbf{F}_n 的第三个元素(即 SnS_n)模 mm

注意:当 n=1n=1 时,n1=0n-1=0A0A^0 是单位矩阵,F1=[1,1,1]T\mathbf{F}_1 = [1,1,1]^TS1=1S_1=1,正确。

另外,可以直接使用 2×22 \times 2 矩阵包含和的信息,但 3×33 \times 3 更清晰。

矩阵快速幂复杂度 O(33logn)=O(27logn)O(3^3 \log n) = O(27 \log n),可以接受。

注意取模运算。