#jZCybttg060502. 1642:【例 2】Fibonacci 第 n 项
1642:【例 2】Fibonacci 第 n 项
1642:【例 2】Fibonacci 第 n 项
题目描述
大家都知道 Fibonacci 数列吧,。
现在问题很简单,输入 和 ,求 。
输入格式
输入 。
输出格式
输出 。
样例
样例输入 #1
5 1000
样例输出 #1
5
样例解释 #1
Fibonacci 数列:。
。
数据范围
对于 的数据:
时空限制
- 时间限制:1000 ms
- 内存限制:524288 KB
注意: 很大,不能直接用递推计算。需要使用矩阵快速幂来加速 Fibonacci 数列的计算。
Fibonacci 数列的递推关系可以用矩阵表示为:
$$\begin{bmatrix} f_{n} & f_{n-1} \end{bmatrix} = \begin{bmatrix} f_{n-1} & f_{n-2} \end{bmatrix} \times \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}$$或者更常见的形式:
$$\begin{bmatrix} f_{n+1} & f_{n} \\ f_{n} & f_{n-1} \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^n$$我们通常使用以下方式:设 $F(n) = \begin{bmatrix} f_{n+1} & f_n \\ f_n & f_{n-1} \end{bmatrix}$,则 $F(n) = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^n$。但我们只需要 。
更简单的:令 ,则 $M^n = \begin{bmatrix} f_{n+1} & f_n \\ f_n & f_{n-1} \end{bmatrix}$。所以要求 ,只需要计算 ,然后取右上角(或左下角)的元素。
因此,算法步骤:
- 定义 矩阵,并实现矩阵乘法(取模 )。
- 用快速幂计算 。
- 输出结果矩阵的右上角元素(即 )。
注意初始值:。对于 或 ,可以直接输出 。但矩阵快速幂也可以处理:当 时,,右上角为 ,即 ;当 时,,右上角为 ,即 。所以对于 ,计算 的右上角?实际上, 的右上角是 ?需要验证。
更常见的方法是:我们想求 ,可以计算 ,然后取左上角?实际上,有公式:
$$\begin{bmatrix} f_n & f_{n-1} \\ f_{n-1} & f_{n-2} \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^{n-1}$$所以 是 的左上角元素。验证:, 是单位矩阵,左上角为 ,即 ;, 左上角为 ,即 。正确。
因此,计算 ,然后输出其左上角元素即可。注意 时,, 是单位矩阵,左上角为 。
所以算法:
- 如果 ,直接输出 (但矩阵快速幂已经可以处理)。
- 否则,计算 ,取结果矩阵的左上角元素。
注意矩阵乘法取模。由于 可能很大(),但矩阵元素在计算过程中不会超过 ?实际上,两个元素相乘可能达到 ,在 long long 范围内。但累加时可能超过 long long?因为最多加两次( 矩阵乘法),所以最大值为 ,仍然在 long long 范围内()。所以可以用 long long 存储中间结果。
实现矩阵快速幂时,注意单位矩阵是 。