春已归来,看美人头上,袅袅春幡。无端风雨,未肯收尽余寒。年时燕子,料今宵梦到西园。浑未办,黄柑荐酒,更传青韭堆盘。
却笑东风,从此便熏梅染柳,更没些闲,闲时又来镜里,转变朱颜。清愁不断,问何人会解连环。生怕见花开花落,朝来塞雁先还。
题目描述
题目连接: https://www.luogu.com.cn/problem/P1962
求第n个斐波拉契数Fibn。Fibn定义如下
Fib1=Fib2=1
Fibn=Fibn−1+Fibn−2,n≥3
由于最终结果很大,因此输出的结果需要对109+7取模。
示例1
输入: 5
输出: 5
示例2
输入: 10
输出: 55
数据范围
1≤n≤263
问题分析
考虑矩阵
An=(Fibn+1Fibn)
如果能够求得矩阵An,自然就求得Fibn了。
我们不难得到矩阵An的递推关系式
An=(Fibn+1Fibn)=(Fibn+Fibn−1Fibn)=(1110)(FibnFibn−1)=(1110)2(Fibn−1Fibn−2)=...=(1110)n−1(Fib2Fib1)=(1110)n−1(11)
由于n的数据范围太大,采用O(n)的算法来计算幂不可行,这里采用快速幂的方法来求幂,时间复杂度为O(logn)。代码如下所示
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| use std::ops;
#[derive(Debug, Clone, Copy)] struct Matrix { matrix : [[u64; 2]; 2] }
impl Matrix { fn new() -> Self { Matrix { matrix: [[1, 1], [1, 0] ] } } }
impl ops::Mul<Matrix> for Matrix { type Output = Matrix;
fn mul(self, _rhs: Matrix) -> Matrix { const N : u64 = 1000000007; let mut ret = Matrix::new(); ret.matrix[0][0] = (self.matrix[0][0] * _rhs.matrix[0][0] + self.matrix[0][1] * _rhs.matrix[1][0]) % N; ret.matrix[0][1] = (self.matrix[0][0] * _rhs.matrix[0][1] + self.matrix[0][1] * _rhs.matrix[1][1]) % N; ret.matrix[1][0] = (self.matrix[1][0] * _rhs.matrix[0][0] + self.matrix[1][1] * _rhs.matrix[1][0]) % N; ret.matrix[1][1] = (self.matrix[1][0] * _rhs.matrix[0][1] + self.matrix[1][1] * _rhs.matrix[1][1]) % N; ret } }
fn pow(matrix: Matrix, n: u64) -> Matrix { if n == 0 { let mut ret = Matrix::new(); ret.matrix[1][1] = 1; return ret; } else if n == 1 { return matrix; } else if n & 1 != 0 { return matrix * pow(matrix, n - 1); } else { let t = pow(matrix, n / 2); return t * t; } }
fn main() { let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let n: u64 = input.trim().parse().unwrap();
if n <= 2 { println!("1"); return; } let matrix = Matrix::new();
let matrix = pow(matrix, n-1); println!("{}", matrix.matrix[0][0]); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <iostream>
struct Matrix { int m00, m01, m10, m11;
Matrix(int m00 = 0, int m01 = 0, int m10 = 0, int m11 = 0) : m00(m00), m01(m01), m10(m10), m11(m11) {} Matrix operator*(const Matrix & matrix) const { Matrix ret; const int N = 1000000007;
ret.m00 = (1ll * m00 * matrix.m00 + 1ll * m01 * matrix.m10) % N; ret.m01 = (1ll * m00 * matrix.m01 + 1ll * m01 * matrix.m11) % N; ret.m10 = (1ll * m10 * matrix.m00 + 1ll * m11 * matrix.m10) % N; ret.m11 = (1ll * m10 * matrix.m01 + 1ll * m11 * matrix.m11) % N; return ret; } };
Matrix pow(const Matrix & matrix, unsigned long long n) { if(n <= 0) { return Matrix(1,1,1,1); } else if(n <= 1) { return matrix; } else if(n & 1 != 0) { return matrix * pow(matrix, n-1); } else { Matrix t = pow(matrix, n >> 1); return t * t; } }
int main(int argc, const char ** argv) { unsigned long long n; std::cin >> n ;
if(n <=2 ) { std::cout << "1" << std::endl; } else { Matrix matrix(1, 1, 1, 0); matrix = pow(matrix, n-1); std::cout << matrix.m00 << std::endl; } return 0; }
|