unsigned long fibonacci(int n) {
if (n <= 2) return 1;
return fibonacci(n-1) + fibonacci(n-2);
}
計算 f(5) 需 12 次加法,大量重複子問題(f(3) 算兩次),時間複雜度 O(2^n),棧深度 O(n),大 n 直接棧溢出。
unsigned long fibonacci(int n) {
if (n <= 2) return 1;
unsigned long f0 = 1, f1 = 1, temp;
for (int i = 3; i <= n; ++i) {
temp = f0 + f1;
f0 = f1;
f1 = temp;
}
return f1;
}
f(5) 僅 3 次加法,消除重複計算。利用矩陣關係:
[f(n) ] = [1 1]^(n-2) * [f(2)]
[f(n-1)] [1 0] [f(1)]
即計算矩陣 M = [[1,1],[1,0]] 的 (n-2) 次方,結果首行兩元素之和為 f(n)。
void matrix_power(ull a,ull b,ull c,ull d, int n,
ull *aa,ull *bb,ull *cc,ull *dd) {
if (n == 1) { *aa=a; *bb=b; *cc=c; *dd=d; return; }
ull xa,xb,xc,xd;
if (n & 1) { // 奇數:M * M^(n-1)
matrix_power(a,b,c,d, n-1, &xa,&xb,&xc,&xd);
*aa = a*xa + b*xc; *bb = a*xb + b*xd;
*cc = c*xa + d*xc; *dd = c*xb + d*xd;
} else { // 偶數:(M^(n/2))^2
matrix_power(a,b,c,d, n>>1, &xa,&xb,&xc,&xd);
*aa = xa*xa + xb*xc; *bb = xa*xb + xb*xd;
*cc = xc*xa + xd*xc; *dd = xc*xb + xd*xd;
}
}
時間 O(log n),但仍用遞歸,棧深 O(log n)。
核心洞察:n 的二進制位為 1 的位置對應 2 的冪次。
M^n = Π M^(2^k)(對所有二進制位 k 為 1 的項相乘)。
迭代過程:
result = I(單位矩陣),base = M。n 的二進制位(從低到高):
result = result * base。base = base * base(平方)。n >>= 1。result。
using ull = unsigned long long;
void multiply(ull *aa, ull *bb, ull *cc, ull *dd,
ull a, ull b, ull c, ull d) {
ull ta = *aa, tb = *bb, tc = *cc, td = *dd;
*aa = ta*a + tb*c; *bb = ta*b + tb*d;
*cc = tc*a + td*c; *dd = tc*b + td*d;
}
void matrix_power(ull a, ull b, ull c, ull d, int n,
ull *aa, ull *bb, ull *cc, ull *dd) {
ull xa = a, xb = b, xc = c, xd = d; // base matrix
*aa = 1; *bb = 0; *cc = 0; *dd = 1; // result = I
bool first = true;
while (n > 0) {
if (n & 1) {
if (first) { // 第一次直接賦值避免乘 I
*aa = a; *bb = b; *cc = c; *dd = d;
first = false;
} else {
multiply(aa, bb, cc, dd, xa, xb, xc, xd);
}
}
// base = base * base
ull ta = xa*xa + xb*xc;
ull tb = xa*xb + xb*xd;
ull tc = xc*xa + xd*xc;
ull td = xc*xb + xd*xd;
xa = ta; xb = tb; xc = tc; xd = td;
n >>= 1;
}
}
| 算法 | 時間複雜度 | 空間 | 加法/乘法次數 | 備註 |
|---|---|---|---|---|
| 朴素遞歸 | O(2^n) | O(n)棧 | 指數級 | 不可用 |
| 迭代累加 | O(n) | O(1) | ~n | 工程常用 |
| 遞歸快速冪 | O(log n) | O(log n)棧 | ~log n 矩陣乘 | 代碼簡潔 |
| 非遞歸快速冪 | O(log n) | O(1) | ~log n 矩陣乘 | 無棧風險,極快 |
本文出自 “菜鳥浮出水” 博客,原文地址:https://rangercyh.blog.51cto.com/1444712/292806