求斐波那契数列的第n项

195 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

求斐波那契数列的第n项

题目描述

求斐波那契数列的第n项(第0项为0,第一项为1),由于结果可能很大,所以需要对结果取模(1e9+7) 其中0<=n<100000

解法一:递归+记忆化,时间复杂度:O(n)

递归加记忆化方法很简单,直接贴代码

#include <iostream>
using namespace std;
const int MOD = 1e9+7, N = 1e5+10;
int mem[N];
int fib(int n) {
    if (n == 0) return 0;
    if (n == 1) return 1;
    if(mem[n]) return mem[n];
    mem[n] = (fib(n - 1) + fib(n - 2)) % MOD;
    return mem[n];
}
int main() {
    int n;
    cin >> n;
    cout << fib(n) << endl;
    return 0;
}

解法二:矩阵快速幂,时间复杂度:O(logn)

[fifi1]=[1110][fi1fi2][fifi1]=[1110]n1[f1f0] \left[\begin{matrix}f_{i}\\f_{i-1}\end{matrix}\right]=\left[\begin{matrix}1&1\\1&0\end{matrix}\right]·\left[\begin{matrix}f_{i-1}\\f_{i-2}\end{matrix}\right] \Rightarrow \left[\begin{matrix}f_{i}\\f_{i-1}\end{matrix}\right] = \left[\begin{matrix}1&1\\1&0\end{matrix}\right]^{n-1}\left[\begin{matrix}f_1\\f_0\end{matrix}\right]

由上述公式即可求出fif_i的值,而[1110]n1\left[\begin{matrix}1&1\\1&0\end{matrix}\right]^{n-1}可以利用快速幂求解,求解时间复杂度为O(logn),所以整体的时间复杂度就为O(logn)

#include <iostream>
using namespace std;
const int MOD = 1e9+7;
struct matrix {
	int a00, a01, a10, a11;
	matrix(int a, int b, int c, int d) {
		a00 = a;
		a01 = b;
		a10 = c;
		a11 = d;
	}
	matrix() {
		a00 = 1;
		a01 = 0;
		a10 = 0;
		a11 = 1;
	}
};

const matrix matr = {1, 1, 1, 0};

matrix mult(matrix a, matrix b) {
	matrix res;
	res.a00 = (a.a00 * b.a00 % MOD + a.a01 * b.a10 % MOD) % MOD;
	res.a01 = (a.a00 % MOD * b.a01 + a.a01 * b.a11 % MOD) % MOD;
	res.a10 = (a.a10 % MOD * b.a00 + a.a11 * b.a10 % MOD) % MOD;
	res.a11 = (a.a10 % MOD * b.a01 + a.a11 * b.a11 % MOD) % MOD;
	return res;
}

matrix qmi(int t) {
	matrix res;
	matrix temp = matr;
	while(t) {
		if(t & 1) res = mult(res, temp);
		temp = mult(temp, temp);
		t >>= 1;
	}
	return res;
}

int main() {
	int n;
	cin >> n;
	if(n == 0) {
		cout << 0 << endl;
		return 0;
	}
	if(n == 1) {
		cout << 1 << endl;
		return 0;
	}
	matrix res = qmi(n - 1);
	int ans = res.a00;
	cout << ans << endl;
	return 0;
}