目录:
- 一、何为斐波那契数列?
- 二、解法一
- 三、解法二
- 四、合二为一
- 五、实际实现
一、何为斐波那契数列?
具体定义如下
二、解法一
记得高中时,数学老师曾让我尝试一下这个问题. 奈何苦思良久没有思路,前段时间算法课上重遇,解法自己从脑子中蹦出来了,也算是一种缘分吧!
对于下面这种形式的递推公式
有一种通用的解法:看着跟等比数列有点儿像,所以想办法 构造出一个等比数列.
两边同时减去 ,原式变为
将左端看作是等比数列 中的 ,右端看作是 ,则有对应系数成比例
整理得
假设该方程的根已求出,为 ,由韦达定理
将 和上式代入 式,得
则 ,所以 .
若 ,则
取
则
若 ,则
取
则
所以
其中 的值通过将初始值
用此方法来求解斐波那契数列的通项公式,数列的递推公式如下:
首先,求解 ,对应方程为
解得
,所以
将
解得
所以
三、解法二
这个解法也是算法课上提到的,不过我把后续的特征分解部分添了上去,这还要得益于高等代数打下的基础!
表示成矩阵形式
为表达简便,用下标表示项数,并记 ,补充定义 ,则
根据矩阵乘法的定义, 即为
问题转化为求 ,emm,看起来好像不是很简单.
嘶,对了,用 特征分解:
阶方阵 ,都可以表示为以下形式:
其中 , 为矩阵 的特征值, 是由 的特征向量拼起来的矩阵. 则
由于 为对角阵,所以 .
首先求矩阵 的特征值,根据定义,有
得到
细心的读者肯定会发现,这和前面的
根据特征向量的定义
求得一个解 . 所以 的一个特征向量为 , 的一个特征向量为 ,取
则
于是
所以
四、合二为一
下面来解释一下为什么特征根 满足的方程与解法一中
考虑一般形式的递推公式:
表示成矩阵形式
解法一中方程的由来我们已经讲得很清楚了,两边同时减去 ,则原式变为
为使 与 为等比数列,需要求上式两边对应系数成比例,而这也可以用行列式表示,两行成比例等价于行列式为零,即
这正是矩阵 的特征值 需满足的方程 .
所以,此文介绍的两种方法本质上是一样的.
五、实际实现
上文已提到,
根据矩阵乘法的定义, 即为
,下面介绍一种快速算法,能够将时间复杂度控制在
先考虑 的快速算法,将 利用二进制进行表示,
,则 可以用连乘形式进行表示.
考虑其中的某一项:
,;
若 ,.
所以具体程序可以这样来写
number power(x,n)
{
s = 1; // 存放结果
t = x; // 记录x^{2^i}
for(i = 0; i <= k; i++)
{
if(d_i != 0) // d_i表示二进制系数
{
s = s*t;
}
t = t*t;
}
return s;
}
上述算法是不完整的,因为没有给出
number power(x,n)
{
s = 1; // 存放结果
a = n; // 记录幂次
t = x; // 记录x^{2^i}
while(a > 0)
{
if(a mod 2) // d_i i=0,1,2,...,k
{
s = s*t;
}
t = t*t;
a = a/2; // 除2取整
}
return s;
}
时间复杂度为 . 类比得到
matrix power(A,m)
{
S = I; // 存放结果,I为单位矩阵
a = m; // 记录幂次
T = A; // 记录A^{2^i}
while(a > 0)
{
if(a mod 2) // d_i i=0,1,2,...,k
{
S = S*T;
}
T = T*T;
a = a/2; // 除2取整
}
return S;
}
所以求斐波那契数列通项的程序(MATLAB版)如下:
function f = fibs(n)
% 函数说明:求斐波那契数列第 n 项的快速算法
S = eye(2); % 单位矩阵
T = [1,1;1,0]; % 递推矩阵
b = n-1;
% 迭代计算
while b > 0
if mod(b,2)
S = S*T;
end
T = T*T;
b = floor(b/2);
end
f = S(1,1);
end