斐波那契数列问题的解
解法一:递归
1 int Fib(int n) 2 { 3 if (n <= 0) 4 return 0; 5 else if (n == 1) 6 return 1; 7 else 8 return Fib(n - 1) + Fib(n - 2); 9 }
解法二:递推
1 int Fib(int n) 2 { 3 if (n <= 0) 4 return 0; 5 else if (n == 1) 6 return 1; 7 8 int first = 0, second = 1; 9 int res = 0; 10 for (int i = 1; i < n; ++i) { 11 res = first + second; 12 first = second; 13 second = res; 14 } 15 return res; 16 }
解法三:分治
通项之间有如下关系:
其中矩阵A为:
根据以下公式,可以log(n)次乘法计算出An。
1 class Matrix { 2 public: 3 Matrix() : m00(0), m01(0), m10(0), m11(0) {} 4 Matrix(int m00, int m01, int m10, int m11) : 5 m00(m00), m01(m01), m10(m10), m11(m11) {} 6 Matrix& operator=(const Matrix& m) { 7 this->m00 = m.m00; 8 this->m01 = m.m01; 9 this->m10 = m.m10; 10 this->m11 = m.m11; 11 return *this; 12 } 13 14 int m00; 15 int m01; 16 int m10; 17 int m11; 18 }; 19 Matrix operator*(const Matrix& lhs, const Matrix& rhs) 20 { 21 Matrix res; 22 res.m00 = lhs.m00 * rhs.m00 + lhs.m01 * rhs.m10; 23 res.m01 = lhs.m00 * rhs.m01 + lhs.m01 * rhs.m11; 24 res.m10 = lhs.m10 * rhs.m00 + lhs.m11 * rhs.m10; 25 res.m11 = lhs.m10 * rhs.m01 + lhs.m11 * rhs.m11; 26 return res; 27 } 28 29 Matrix MatrixPow(const Matrix& m, int n) 30 { 31 Matrix res(1, 0, 0, 1); 32 Matrix base = m; 33 for (; n; n >>= 1) { 34 if (n & 1) 35 res = res * base; 36 base = base * base; 37 } 38 return res; 39 } 40 41 int Fib(int n) 42 { 43 if (n <= 0) 44 return 0; 45 else if (n == 1) 46 return 1; 47 48 Matrix A(1, 1, 1, 0); 49 Matrix m = MatrixPow(A, n - 1); 50 51 return m.m00; 52 }
函数MatrixPow的写法似乎不像分治,实际上我们把它写成下面这样就比较明显了,时间复杂度O(logn)。
1 Matrix MatrixPow(const Matrix& m, int n) 2 { 3 if (n == 1) 4 return m; 5 if (n % 2 == 0) 6 return MatrixPow(m * m, n / 2); 7 else 8 return MatrixPow(m * m, n / 2) * m; 9 }