logN求Fibonacci數列第N項
- 斐波那契數列通項公式
- 以下介紹兩種複雜度爲的算法
- 兩種方法思想類似
1. 動態規劃
- 當我們嘗試將和進行繼續拆解時(始終保持兩項),發現兩項的係數始終是斐波那契數列中的某一相鄰兩項
- 因此,F(i)一定可以可以由4個項組成
- 當時則爲
- 且a,b,x具有一定關係
思路
a,b,x有多種可能
此時需要算4個小項才能合併到1個大項
若這4個項中有相同的項,則可以簡化計算
此外,越大的項,計算的複雜度越大,反之越小
因此我們可以想到取 附近的項
- 通過遞推得(也可以用較小的找找規律)
- 當爲奇數時,
- 當爲偶數時,
即我們將一個遞推項分成2或3項分別計算後再合併
- 可以分析複雜度爲
- 注:在實際程序實現中,不能直接
return F(i/2+1)*F(i/2)+F(i/2)*F(i/2-1)
,這樣會造成計算冗餘- 應該先保存下結果,計算後
return
DP代碼
int Fibonacci(int x) // logN
{
if (x == 1 || x == 2) return 1;
if (x % 2 != 0)
{
int F1 = Fibonacci(x / 2 + 1), F2 = Fibonacci(x / 2);
return F1 * F1 + F2 * F2;
}
else
{
int F1 = Fibonacci(x / 2 + 1), F2 = Fibonacci(x / 2), F3 = Fibonacci(x / 2 - 1);
return F1 * F2 + F2 * F3;
}
}
2. 矩陣分治
- 結合矩陣的知識,我們可以知道斐波那契數列符合
- 於是隨着等號右邊中的斐波那契項的項數降低,該矩陣就不斷左乘
因此可以基於矩陣結合律計算若干項矩陣乘積,再左乘
- 設該矩陣爲A
- 則
- 其中只需計算一項
- 依次類推
這就是
快速冪
的思想快速冪講解
代碼
int[2][2] Matrix(int x)
{
int a[2][2] = { { 1, 1 }, { 0, 1 } };
if (x == 1) return a;
int b[2][2] = Matrix(x / 2);
if (x % 2 == 0) return b * b; // 省略矩陣乘法
return b * b * a;
}