我们知道斐波那契数列:1 1 2 3 5 8 13 ……
这个可以通过递归或DP来实现。但是如果我们要求第10^9个斐波那契数列怎么办?
这就没办法用递归去跑了。
这里则有一个求矩阵幂方法。我们先记住公式……
[Fn+1, Fn = [1 1 的 n 次方
Fn-1, Fn ] 1 0 ]
那么则可以把Fn表示成多个矩阵相乘的形式。
然后我们要做的,是求矩阵的 n 次幂:
A^n = A^(n/2) * A^(n/2) ,当n为偶数
A^n = A^((n-1)/2) * A^((n-1)/2) * A,当n为奇数
通过这种方式可以将复杂度降到 log(n)。
然后,这里涉及到两个矩阵相乘,如果两个矩阵可以相乘,比如A,B相乘。
则说明A的列等于B的行。
我们知道公式 Cij = k求和 { Aik * Bkj }
至此,完成了我们的思路,下面是代码。
class Solution {
public:
struct mat {
int m[2][2];
};
int Fibonacci(int n) {
mat base;
base.m[0][0] = 1;
base.m[0][1] = 1;
base.m[1][0] = 1;
base.m[1][1] = 0;
mat res = expMatrix(base, n);
return res.m[0][1];
}
mat expMatrix(mat base, int n) {
if (0 == n) {
mat res;
res.m[0][0] = 1;
res.m[0][1] = 0;
res.m[1][0] = 0;
res.m[1][1] = 1;
return res;
}
if (1 == n) {
return base;
}
mat res = expMatrix(base, n >> 1);
res = mulMatrix(res, res);
if (1 == n % 2) {
res = mulMatrix(res, base);
}
return res;
}
mat mulMatrix(mat a, mat b) {
mat res;
memset(res.m, 0, sizeof(res.m));
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
res.m[i][j] += a.m[i][k] * b.m[k][j];
}
}
}
return res;
}
};