前情
本文內容首先需要了解快速冪的實現原理,詳情見 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