前情
本文内容首先需要了解快速幂的实现原理,详情见 pow(x, n)快速幂实现
题目
leetcode链接: https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/
题目描述:
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入:n = 2
输出:1
示例 2:
输入:n = 5
输出:5
提示:
0 <= n <= 100
解法
朴素的解法就不写了,小学生都会TAT , 这里给出矩阵快速幂的解法
首先给出斐波那契数列定义
将 用矩阵表示则有
而 有着同样的表示方法,则递推得到
而 可以用矩阵快速幂算出来,这里不再赘述矩阵乘法以及快速幂了, 则我们可以用 的时间计算出来,注意这里我们将2阶矩阵的乘法当作常数才可以得到这个结论。
代码
class Solution {
public:
const long long mod = 1000000007;
vector<vector<int>> mat_mul(vector<vector<int>> a, vector<vector<int>> b)
{
int ra = a.size(), ca = a[0].size(), rb = b.size(), cb = b[0].size();
vector<vector<int> > res(ra, vector<int>(cb, 0));
for (int k=0; k<ca; k++)
for (int i=0; i<ra; i++)
for (int j=0; j<cb; j++)
{
res[i][j] += ((a[i][k]%mod)*(b[k][j]%mod))%mod;
}
return res;
}
vector<vector<int>> quick_mat_pow(vector<vector<int>> a, int n)
{
vector<vector<int>> res = {{1, 0},{0, 1}};
vector<vector<int>> p = a;
int t = n;
for (; t>0; t>>=1)
{
if (t&1) res = mat_mul(res, p);
p = mat_mul(p, p);
}
return res;
}
int fib(int n) {
vector<vector<int>> f = {{1}, {0}};
if (n<2) {
if (n==0) return 0;
else return 1;
}
vector<vector<int>> base = {{1,1},{1,0}};
return mat_mul(quick_mat_pow(base, n-1), f)[0][0];
}
};
最后想说;
我的源码都整理在了github上,剑指offer专题会分类整理(如树专题,DP专题,模拟专题,搜索专题等),github链接见下文,如果对您有帮助,请帮忙在github中star,这对我很重要!!!! 拜托拜托~!!
github链接: https://github.com/wjlpku/Leetcode-interview