目录:

  • 一、何为斐波那契数列?
  • 二、解法一
  • 三、解法二
  • 四、合二为一
  • 五、实际实现


一、何为斐波那契数列?

斐波那契 python 斐波那契数列通项_斐波那契 python

具体定义如下

斐波那契 python 斐波那契数列通项_斐波那契数列_02

二、解法一

记得高中时,数学老师曾让我尝试一下这个问题. 奈何苦思良久没有思路,前段时间算法课上重遇,解法自己从脑子中蹦出来了,也算是一种缘分吧!

对于下面这种形式的递推公式
斐波那契 python 斐波那契数列通项_斐波那契数列_03

有一种通用的解法:看着跟等比数列有点儿像,所以想办法 构造出一个等比数列.

两边同时减去 斐波那契 python 斐波那契数列通项_斐波那契数列_04,原式变为
斐波那契 python 斐波那契数列通项_等比数列_05

将左端看作是等比数列 斐波那契 python 斐波那契数列通项_斐波那契数列_06 中的 斐波那契 python 斐波那契数列通项_斐波那契 python_07,右端看作是 斐波那契 python 斐波那契数列通项_特征分解_08,则有对应系数成比例
斐波那契 python 斐波那契数列通项_斐波那契 python_09

整理得
斐波那契 python 斐波那契数列通项_斐波那契 python_10

假设该方程的根已求出,为 斐波那契 python 斐波那契数列通项_斐波那契 python_11,由韦达定理
斐波那契 python 斐波那契数列通项_斐波那契 python_12

斐波那契 python 斐波那契数列通项_特征分解_13 和上式代入 斐波那契 python 斐波那契数列通项_递推公式_14 式,得
斐波那契 python 斐波那契数列通项_特征分解_15

斐波那契 python 斐波那契数列通项_特征分解_16,所以 斐波那契 python 斐波那契数列通项_特征分解_17.
斐波那契 python 斐波那契数列通项_递推公式_18

斐波那契 python 斐波那契数列通项_递推公式_19,则
斐波那契 python 斐波那契数列通项_斐波那契 python_20


斐波那契 python 斐波那契数列通项_斐波那契数列_21


斐波那契 python 斐波那契数列通项_递推公式_22
斐波那契 python 斐波那契数列通项_递推公式_23,则
斐波那契 python 斐波那契数列通项_斐波那契数列_24

斐波那契 python 斐波那契数列通项_斐波那契数列_25


斐波那契 python 斐波那契数列通项_特征分解_26

所以
斐波那契 python 斐波那契数列通项_特征分解_27

其中 斐波那契 python 斐波那契数列通项_斐波那契 python_28 的值通过将初始值 斐波那契 python 斐波那契数列通项_递推公式_29

用此方法来求解斐波那契数列的通项公式,数列的递推公式如下:
斐波那契 python 斐波那契数列通项_斐波那契数列_30

首先,求解 斐波那契 python 斐波那契数列通项_斐波那契数列_31,对应方程为
斐波那契 python 斐波那契数列通项_斐波那契 python_32

解得
斐波那契 python 斐波那契数列通项_递推公式_33

斐波那契 python 斐波那契数列通项_递推公式_23,所以
斐波那契 python 斐波那契数列通项_递推公式_35

斐波那契 python 斐波那契数列通项_递推公式_29

斐波那契 python 斐波那契数列通项_递推公式_37

解得
斐波那契 python 斐波那契数列通项_斐波那契 python_38

所以
斐波那契 python 斐波那契数列通项_递推公式_39

三、解法二

这个解法也是算法课上提到的,不过我把后续的特征分解部分添了上去,这还要得益于高等代数打下的基础!

斐波那契 python 斐波那契数列通项_递推公式_40

表示成矩阵形式
斐波那契 python 斐波那契数列通项_等比数列_41

为表达简便,用下标表示项数,并记 斐波那契 python 斐波那契数列通项_斐波那契数列_42,补充定义 斐波那契 python 斐波那契数列通项_递推公式_43,则
斐波那契 python 斐波那契数列通项_斐波那契 python_44

根据矩阵乘法的定义, 斐波那契 python 斐波那契数列通项_等比数列_45 即为 斐波那契 python 斐波那契数列通项_特征分解_46

问题转化为求 斐波那契 python 斐波那契数列通项_特征分解_46,emm,看起来好像不是很简单.

嘶,对了,用 特征分解

斐波那契 python 斐波那契数列通项_特征分解_48 阶方阵 斐波那契 python 斐波那契数列通项_等比数列_49,都可以表示为以下形式:

斐波那契 python 斐波那契数列通项_等比数列_50

其中 斐波那契 python 斐波那契数列通项_特征分解_51斐波那契 python 斐波那契数列通项_特征分解_52 为矩阵 斐波那契 python 斐波那契数列通项_等比数列_49 的特征值,斐波那契 python 斐波那契数列通项_等比数列_54 是由 斐波那契 python 斐波那契数列通项_等比数列_49 的特征向量拼起来的矩阵. 则
斐波那契 python 斐波那契数列通项_斐波那契数列_56

由于 斐波那契 python 斐波那契数列通项_特征分解_57 为对角阵,所以 斐波那契 python 斐波那契数列通项_等比数列_58.

首先求矩阵 斐波那契 python 斐波那契数列通项_等比数列_49 的特征值,根据定义,有
斐波那契 python 斐波那契数列通项_递推公式_60

得到
斐波那契 python 斐波那契数列通项_等比数列_61

细心的读者肯定会发现,这和前面的 斐波那契 python 斐波那契数列通项_斐波那契 python_62

斐波那契 python 斐波那契数列通项_递推公式_63

根据特征向量的定义
斐波那契 python 斐波那契数列通项_等比数列_64

求得一个解 斐波那契 python 斐波那契数列通项_斐波那契 python_65. 所以 斐波那契 python 斐波那契数列通项_特征分解_66 的一个特征向量为 斐波那契 python 斐波那契数列通项_递推公式_67斐波那契 python 斐波那契数列通项_斐波那契数列_68 的一个特征向量为 斐波那契 python 斐波那契数列通项_斐波那契数列_69,取
斐波那契 python 斐波那契数列通项_特征分解_70


斐波那契 python 斐波那契数列通项_递推公式_71

于是
斐波那契 python 斐波那契数列通项_递推公式_72

所以
斐波那契 python 斐波那契数列通项_特征分解_73

四、合二为一

下面来解释一下为什么特征根 斐波那契 python 斐波那契数列通项_斐波那契 python_74 满足的方程与解法一中 斐波那契 python 斐波那契数列通项_斐波那契数列_31

斐波那契 python 斐波那契数列通项_等比数列_76

考虑一般形式的递推公式:

斐波那契 python 斐波那契数列通项_斐波那契数列_77

表示成矩阵形式
斐波那契 python 斐波那契数列通项_斐波那契数列_78

解法一中方程的由来我们已经讲得很清楚了,两边同时减去 斐波那契 python 斐波那契数列通项_斐波那契数列_04,则原式变为
斐波那契 python 斐波那契数列通项_等比数列_80

为使 斐波那契 python 斐波那契数列通项_特征分解_81斐波那契 python 斐波那契数列通项_递推公式_82 为等比数列,需要求上式两边对应系数成比例,而这也可以用行列式表示,两行成比例等价于行列式为零,即
斐波那契 python 斐波那契数列通项_斐波那契 python_83

这正是矩阵 斐波那契 python 斐波那契数列通项_等比数列_49 的特征值 斐波那契 python 斐波那契数列通项_斐波那契 python_74 需满足的方程 斐波那契 python 斐波那契数列通项_斐波那契 python_86.

所以,此文介绍的两种方法本质上是一样的.

五、实际实现

斐波那契 python 斐波那契数列通项_特征分解_48

  上文已提到,
斐波那契 python 斐波那契数列通项_递推公式_88

根据矩阵乘法的定义,斐波那契 python 斐波那契数列通项_等比数列_45 即为 斐波那契 python 斐波那契数列通项_斐波那契 python_90

斐波那契 python 斐波那契数列通项_斐波那契 python_90,下面介绍一种快速算法,能够将时间复杂度控制在 斐波那契 python 斐波那契数列通项_等比数列_92

先考虑 斐波那契 python 斐波那契数列通项_斐波那契数列_93 的快速算法,将 斐波那契 python 斐波那契数列通项_特征分解_48 利用二进制进行表示,
斐波那契 python 斐波那契数列通项_等比数列_95

斐波那契 python 斐波那契数列通项_等比数列_96,则 斐波那契 python 斐波那契数列通项_斐波那契数列_93 可以用连乘形式进行表示.
斐波那契 python 斐波那契数列通项_特征分解_98

考虑其中的某一项:

斐波那契 python 斐波那契数列通项_斐波那契数列_99斐波那契 python 斐波那契数列通项_特征分解_100
  若 斐波那契 python 斐波那契数列通项_斐波那契 python_101斐波那契 python 斐波那契数列通项_斐波那契 python_102.

所以具体程序可以这样来写

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;
}

上述算法是不完整的,因为没有给出 斐波那契 python 斐波那契数列通项_递推公式_103

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;
}

时间复杂度为 斐波那契 python 斐波那契数列通项_等比数列_92. 类比得到 斐波那契 python 斐波那契数列通项_斐波那契数列_105

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