一、何为斐波那契数列?
1 , 1 , 2 , 3 , 5 , 8 , 13 , ⋯ 1,1,2,3,5,8,13,\cdots 1,1,2,3,5,8,13,⋯
具体定义如下
{
f
(
n
)
=
f
(
n
−
1
)
+
f
(
n
−
2
)
,
n
≥
3
f
(
1
)
=
f
(
2
)
=
1
\begin{cases} f(n)=f(n-1)+f(n-2),\quad n \geq 3\\ f(1)=f(2)=1 \end{cases}
{f(n)=f(n−1)+f(n−2),n≥3f(1)=f(2)=1
二、解法一
记得高中时,数学老师曾让我尝试一下这个问题. 奈何苦思良久没有思路,前段时间算法课上重遇,解法自己从脑子中蹦出来了,也算是一种缘分吧!
对于下面这种形式的递推公式
f
(
n
)
=
a
f
(
n
−
1
)
+
b
f
(
n
−
2
)
(
b
≠
0
)
f(n)=af(n-1)+bf(n-2) \quad(b\neq0)
f(n)=af(n−1)+bf(n−2)(b=0)
有一种通用的解法:看着跟等比数列有点儿像,所以想办法 构造出一个等比数列.
两边同时减去
k
f
(
n
−
1
)
kf(n-1)
kf(n−1),原式变为
f
(
n
)
−
k
f
(
n
−
1
)
=
(
a
−
k
)
f
(
n
−
1
)
+
b
f
(
n
−
2
)
(*)
f(n)-kf(n-1)=(a-k)f(n-1)+bf(n-2) \tag{*}
f(n)−kf(n−1)=(a−k)f(n−1)+bf(n−2)(*)
将左端看作是等比数列
{
a
n
}
\{a_n\}
{an} 中的
a
n
a_n
an,右端看作是
(
a
−
k
)
a
n
−
1
(a-k)\,a_{n-1}
(a−k)an−1,则有对应系数成比例
1
a
−
k
=
−
k
b
\frac{1}{a-k}=\frac{-k}{b}
a−k1=b−k
整理得
k
2
−
a
k
−
b
=
0
k^2-ak-b=0
k2−ak−b=0
假设该方程的根已求出,为
k
1
,
k
2
k_1,k_2
k1,k2,由韦达定理
a
=
k
1
+
k
2
,
b
=
−
k
1
k
2
a=k_1+k_2,\,\,b=-k_1k_2
a=k1+k2,b=−k1k2
将
k
=
k
1
k=k_1
k=k1 和上式代入
(
∗
)
(*)
(∗) 式,得
f
(
n
)
−
k
1
f
(
n
−
1
)
=
k
2
(
f
(
n
−
1
)
−
k
1
f
(
n
−
2
)
)
f(n)-k_1f(n-1)=k_2\big(f(n-1)-k_1f(n-2)\big)
f(n)−k1f(n−1)=k2(f(n−1)−k1f(n−2))
则
a
n
=
k
2
a
n
−
1
a_n=k_2 a_{n-1}
an=k2an−1,所以
a
n
=
k
2
n
−
2
a
2
a_n=k_2^{n-2}a_2
an=k2n−2a2.
f
(
n
)
=
k
1
f
(
n
−
1
)
+
k
2
n
−
2
a
2
=
k
1
2
f
(
n
−
2
)
+
k
1
k
2
n
−
3
a
2
+
k
2
n
−
2
a
2
=
k
1
n
−
1
f
(
1
)
+
a
2
(
k
1
n
−
2
k
2
0
+
k
1
n
−
3
k
2
1
+
⋯
+
k
1
1
k
2
n
−
3
+
k
2
n
−
2
)
\begin{aligned} f(n)&=k_1f(n-1)+k_2^{n-2}a_2\\&= k_1^2f(n-2)+k_1k_2^{n-3}a_2+k_2^{n-2}a_2\\&= k_1^{n-1}f(1)+a_2\big(k_1^{n-2}{k_2}^{0}+k_1^{n-3}k_2^{1}+\cdots+k_1^1k_2^{n-3}+k_2^{n-2}\big) \end{aligned}
f(n)=k1f(n−1)+k2n−2a2=k12f(n−2)+k1k2n−3a2+k2n−2a2=k1n−1f(1)+a2(k1n−2k20+k1n−3k21+⋯+k11k2n−3+k2n−2)
若
k
1
=
k
2
=
k
k_1=k_2=k
k1=k2=k,则
f
(
n
)
=
k
n
−
1
f
(
1
)
+
a
2
(
n
−
1
)
k
n
−
2
=
k
n
(
f
(
1
)
k
−
a
2
k
2
+
a
2
k
2
n
)
f(n)=k^{n-1}f(1)+a_2(n-1)k^{n-2}=k^n(\frac{f(1)}{k}-\frac{a_2}{k^2}+\frac{a_2}{k^2}n)
f(n)=kn−1f(1)+a2(n−1)kn−2=kn(kf(1)−k2a2+k2a2n)
取
c
1
=
f
(
1
)
k
−
a
2
k
2
,
c
2
=
a
2
k
2
c_1=\frac{f(1)}{k}-\frac{a_2}{k^2},\,\,c_2=\frac{a_2}{k^2}
c1=kf(1)−k2a2,c2=k2a2
则
f
(
n
)
=
(
c
1
+
n
c
2
)
k
n
f(n)=(c_1+nc_2)k^n
f(n)=(c1+nc2)kn
若
k
1
≠
k
2
k_1\neq k_2
k1=k2,则
f
(
n
)
=
k
1
n
−
1
f
(
1
)
+
a
2
k
1
n
−
2
(
1
−
(
k
2
/
k
1
)
n
−
1
)
1
−
k
2
/
k
1
=
k
1
n
−
1
f
(
1
)
+
a
2
k
1
n
−
1
−
k
2
n
−
1
k
1
−
k
2
=
1
k
1
(
f
(
1
)
+
a
2
k
1
−
k
2
)
k
1
n
+
1
k
2
(
−
a
2
k
1
−
k
2
)
k
2
n
\begin{aligned} f(n)&=k_1^{n-1}f(1)+a_2\frac{k_1^{n-2}(1-(k_2/k_1)^{n-1})}{1-k_2/k_1}\\&= k_1^{n-1}f(1)+a_2\frac{k_1^{n-1}-k_2^{n-1}}{k_1-k_2}\\&= \frac{1}{k_1}\big(f(1)+\frac{a_2}{k_1-k_2}\big)k_1^{n}+\frac{1}{k_2}(-\frac{a_2}{k_1-k_2})k_2^{n} \end{aligned}
f(n)=k1n−1f(1)+a21−k2/k1k1n−2(1−(k2/k1)n−1)=k1n−1f(1)+a2k1−k2k1n−1−k2n−1=k11(f(1)+k1−k2a2)k1n+k21(−k1−k2a2)k2n
取
c 1 = 1 k 1 ( f ( 1 ) + a 2 k 1 − k 2 ) , c 2 = 1 k 2 ( − a 2 k 1 − k 2 ) c_1=\frac{1}{k_1}\big(f(1)+\frac{a_2}{k_1-k_2}\big),\,\,c_2=\frac{1}{k_2}(-\frac{a_2}{k_1-k_2}) c1=k11(f(1)+k1−k2a2),c2=k21(−k1−k2a2)
则
f
(
n
)
=
c
1
k
1
n
+
c
2
k
2
n
f(n)=c_1k_1^n+c_2k_2^n
f(n)=c1k1n+c2k2n
所以
f
(
n
)
=
{
c
1
k
1
n
+
c
2
k
2
n
,
k
1
≠
k
2
(
c
1
+
n
c
2
)
k
n
,
k
1
=
k
2
=
k
f(n)= \begin{cases} c_1k_1^n+c_2k_2^n, & k_1\neq k_2 \\ (c_1+nc_2)k^n, & k_1=k_2=k \end{cases}
f(n)={c1k1n+c2k2n,(c1+nc2)kn,k1=k2k1=k2=k
其中 c 1 , c 2 c_1,c_2 c1,c2 的值通过将初始值 f ( 1 ) , f ( 2 ) f(1),f(2) f(1),f(2) 代入求得.
用此方法来求解斐波那契数列的通项公式,数列的递推公式如下:
f
(
n
)
=
f
(
n
−
1
)
+
f
(
n
−
2
)
f(n)=f(n-1)+f(n-2)
f(n)=f(n−1)+f(n−2)
首先,求解
k
k
k,对应方程为
k
2
−
k
−
1
=
0
k^2-k-1=0
k2−k−1=0
解得
k
1
=
1
+
5
2
,
k
2
=
1
−
5
2
k_1=\frac{1+\sqrt{5}}{2},\,\,k_2=\frac{1-\sqrt{5}}{2}
k1=21+5,k2=21−5
k
1
≠
k
2
k_1\neq k_2
k1=k2,所以
f
(
n
)
=
c
1
k
1
n
+
c
2
k
2
n
f(n)=c_1{k_1}^n+c_2{k_2}^n
f(n)=c1k1n+c2k2n
将 f ( 1 ) , f ( 2 ) f(1),f(2) f(1),f(2) 的值代入,得
{ f ( 1 ) = c 1 k 1 + c 2 k 2 = 1 f ( 2 ) = c 1 k 1 2 + c 2 k 2 2 = 1 \begin{cases} \begin{aligned} f(1)&=c_1k_1+c_2k_2=1 \\ f(2)&=c_1{k_1}^2+c_2{k_2}^2=1 \end{aligned} \end{cases} {f(1)f(2)=c1k1+c2k2=1=c1k12+c2k22=1
解得
c
1
=
1
5
,
c
2
=
−
1
5
c_1=\frac{1}{\sqrt{5}},\,\,c_2=-\frac{1}{\sqrt{5}}
c1=51,c2=−51
所以
f
(
n
)
=
1
5
(
1
+
5
2
)
n
−
1
5
(
1
−
5
2
)
n
f(n)=\frac{1}{\sqrt{5}}\big(\frac{1+\sqrt{5}}{2}\big)^n-\frac{1}{\sqrt{5}}\big(\frac{1-\sqrt{5}}{2}\big)^n
f(n)=51(21+5)n−51(21−5)n
三、解法二
这个解法也是算法课上提到的,不过我把后续的特征分解部分添了上去,这还要得益于高等代数打下的基础!
f ( n ) = f ( n − 1 ) + f ( n − 2 ) f ( n − 1 ) = f ( n − 1 ) \begin{aligned} f(n)&=f(n-1)+f(n-2)\\ f(n-1)&=f(n-1) \end{aligned} f(n)f(n−1)=f(n−1)+f(n−2)=f(n−1)
表示成矩阵形式
(
f
(
n
)
f
(
n
−
1
)
)
=
(
1
1
1
0
)
(
f
(
n
−
1
)
f
(
n
−
2
)
)
\begin{pmatrix}f(n)\\f(n-1)\end{pmatrix}=\begin{pmatrix}1 & 1\\1 & 0\end{pmatrix}\begin{pmatrix}f(n-1)\\f(n-2)\end{pmatrix}
(f(n)f(n−1))=(1110)(f(n−1)f(n−2))
为表达简便,用下标表示项数,并记
A
=
(
1
1
1
0
)
\displaystyle A=\begin{pmatrix}1 & 1\\1 & 0\end{pmatrix}
A=(1110),补充定义
f
(
0
)
=
f
0
=
0
f(0)=f_0=0
f(0)=f0=0,则
(
f
n
f
n
−
1
)
=
A
(
f
n
−
1
f
n
−
2
)
=
A
2
(
f
n
−
2
f
n
−
3
)
=
⋯
=
A
n
−
1
(
f
1
f
0
)
=
A
n
−
1
(
1
0
)
\begin{pmatrix}f_n\\f_{n-1}\end{pmatrix}= A\begin{pmatrix}f_{n-1}\\f_{n-2}\end{pmatrix}= A^2\begin{pmatrix}f_{n-2}\\f_{n-3}\end{pmatrix}= \cdots = A^{n-1}\begin{pmatrix}f_{1}\\f_{0}\end{pmatrix}= A^{n-1}\begin{pmatrix}1\\0\end{pmatrix}
(fnfn−1)=A(fn−1fn−2)=A2(fn−2fn−3)=⋯=An−1(f1f0)=An−1(10)
根据矩阵乘法的定义, f n f_n fn 即为 A n − 1 A^{n-1} An−1 首行首列的元素.
问题转化为求 A n − 1 A^{n-1} An−1,emm,看起来好像不是很简单.
嘶,对了,用 特征分解:
任何一个 n n n 阶方阵 A A A,都可以表示为以下形式:
A = V D V − 1 A=VDV^{-1} A=VDV−1
其中
D
=
d
i
a
g
(
λ
1
,
λ
2
,
⋯
,
λ
n
)
D=diag(\lambda_1,\lambda_2,\cdots,\lambda_n)
D=diag(λ1,λ2,⋯,λn),
λ
i
\lambda_i
λi 为矩阵
A
A
A 的特征值,
V
V
V 是由
A
A
A 的特征向量拼起来的矩阵. 则
A
m
=
(
V
D
V
−
1
)
m
=
V
D
V
−
1
V
D
V
−
1
⋯
V
D
V
−
1
=
V
D
(
V
−
1
V
)
D
(
V
−
1
V
)
⋯
D
V
−
1
=
V
D
m
V
−
1
\begin{aligned} A^m=(VDV^{-1})^m&=VDV^{-1}VDV^{-1}\cdots VDV^{-1}\\&= VD(V^{-1}V)D(V^{-1}V)\cdots DV^{-1}\\&=VD^mV^{-1} \end{aligned}
Am=(VDV−1)m=VDV−1VDV−1⋯VDV−1=VD(V−1V)D(V−1V)⋯DV−1=VDmV−1
由于 D D D 为对角阵,所以 D m = d i a g ( λ 1 m , λ 2 m , ⋯ , λ n m ) D^m=diag(\lambda_1^m,\lambda_2^m,\cdots,\lambda_n^m) Dm=diag(λ1m,λ2m,⋯,λnm).
首先求矩阵
A
A
A 的特征值,根据定义,有
∣
A
−
λ
I
∣
=
∣
1
−
λ
1
1
−
λ
∣
=
0
\left|A-\lambda I\right|= \left|\begin{array}{cccc} 1-\lambda & 1 \\ 1 & -\lambda \end{array}\right|=0
∣A−λI∣=∣∣∣∣1−λ11−λ∣∣∣∣=0
得到
λ
2
−
λ
−
1
=
0
\lambda^2-\lambda-1=0
λ2−λ−1=0
细心的读者肯定会发现,这和前面的 k 2 − k − 1 = 0 k^2-k-1=0 k2−k−1=0 实际上是同一个方程(其实这并不是巧合,具体原因会在文末分析),所以解也是一样的.
λ 1 = 1 + 5 2 , λ 2 = 1 − 5 2 \lambda_1=\frac{1+\sqrt{5}}{2},\,\,\lambda_2=\frac{1-\sqrt{5}}{2} λ1=21+5,λ2=21−5
根据特征向量的定义
(
A
−
λ
I
)
x
=
0
(A-\lambda I)x=0
(A−λI)x=0
求得一个解
x
=
(
λ
,
1
)
T
x=(\lambda,1)^T
x=(λ,1)T. 所以
λ
1
\lambda_1
λ1 的一个特征向量为
(
λ
1
,
1
)
T
(\lambda_1,1)^T
(λ1,1)T,
λ
2
\lambda_2
λ2 的一个特征向量为
(
λ
2
,
1
)
T
(\lambda_2,1)^T
(λ2,1)T,取
V
=
(
λ
1
λ
2
1
1
)
V=\begin{pmatrix}\lambda_1 & \lambda_2 \\1 & 1\end{pmatrix}
V=(λ11λ21)
则
V
−
1
=
1
λ
1
−
λ
2
(
1
−
λ
2
−
1
λ
1
)
V^{-1}=\frac{1}{\lambda_1-\lambda_2} \begin{pmatrix}1 & -\lambda_2\\ -1 & \lambda_1\end{pmatrix}
V−1=λ1−λ21(1−1−λ2λ1)
于是
(
f
n
f
n
−
1
)
=
A
n
−
1
(
1
0
)
=
V
D
n
−
1
V
−
1
(
1
0
)
=
1
λ
1
−
λ
2
(
λ
1
λ
2
1
1
)
(
λ
1
n
−
1
0
0
λ
2
n
−
1
)
(
1
−
λ
2
−
1
λ
1
)
(
1
0
)
=
1
λ
1
−
λ
2
(
λ
1
n
λ
2
n
λ
1
n
−
1
λ
2
n
−
1
)
(
1
−
1
)
=
1
λ
1
−
λ
2
(
λ
1
n
−
λ
2
n
λ
1
n
−
1
−
λ
2
n
−
1
)
\begin{aligned} \begin{pmatrix}f_n\\f_{n-1}\end{pmatrix}&= A^{n-1}\begin{pmatrix}1\\0\end{pmatrix}\\&= VD^{n-1}V^{-1}\begin{pmatrix}1\\0\end{pmatrix}\\&= \frac{1}{\lambda_1-\lambda_2} \begin{pmatrix}\lambda_1 & \lambda_2 \\1 & 1\end{pmatrix} \begin{pmatrix}\lambda_1^{n-1} & 0\\0 & \lambda_2^{n-1}\end{pmatrix} \begin{pmatrix}1 & -\lambda_2\\ -1 & \lambda_1\end{pmatrix} \begin{pmatrix}1\\0\end{pmatrix}\\&= \frac{1}{\lambda_1-\lambda_2} \begin{pmatrix}\lambda_1^{n} & \lambda_2^{n}\\\lambda_1^{n-1} & \lambda_2^{n-1}\end{pmatrix} \begin{pmatrix}1\\-1\end{pmatrix}\\&= \frac{1}{\lambda_1-\lambda_2} \begin{pmatrix}\lambda_1^{n}-\lambda_2^{n}\\\lambda_1^{n-1}-\lambda_2^{n-1}\end{pmatrix} \end{aligned}
(fnfn−1)=An−1(10)=VDn−1V−1(10)=λ1−λ21(λ11λ21)(λ1n−100λ2n−1)(1−1−λ2λ1)(10)=λ1−λ21(λ1nλ1n−1λ2nλ2n−1)(1−1)=λ1−λ21(λ1n−λ2nλ1n−1−λ2n−1)
所以
f
(
n
)
=
1
λ
1
−
λ
2
(
λ
1
n
−
λ
2
n
)
=
1
5
(
(
1
+
5
2
)
n
−
(
1
−
5
2
)
n
)
f(n)=\frac{1}{\lambda_1-\lambda_2}(\lambda_1^{n}-\lambda_2^{n})=\frac{1}{\sqrt{5}}\Big(\big(\frac{1+\sqrt{5}}{2}\big)^n-\big(\frac{1-\sqrt{5}}{2}\big)^n\Big)
f(n)=λ1−λ21(λ1n−λ2n)=51((21+5)n−(21−5)n)
四、合二为一
下面来解释一下为什么特征根 λ \lambda λ 满足的方程与解法一中 k k k 满足的方程相同.
x 2 − x − 1 = 0 x^2-x-1=0 x2−x−1=0
考虑一般形式的递推公式:
f ( n ) = a f ( n − 1 ) + b f ( n − 2 ) f(n)=af(n-1)+bf(n-2) f(n)=af(n−1)+bf(n−2)
表示成矩阵形式
(
f
n
f
n
−
1
)
=
(
a
b
1
0
)
(
f
n
−
1
f
n
−
2
)
=
A
(
f
n
−
1
f
n
−
2
)
\begin{pmatrix}f_n\\f_{n-1}\end{pmatrix}= \begin{pmatrix}a & b\\1 & 0\\\end{pmatrix} \begin{pmatrix}f_{n-1}\\f_{n-2}\end{pmatrix}= A\begin{pmatrix}f_{n-1}\\f_{n-2}\end{pmatrix}
(fnfn−1)=(a1b0)(fn−1fn−2)=A(fn−1fn−2)
解法一中方程的由来我们已经讲得很清楚了,两边同时减去
k
f
(
n
−
1
)
kf(n-1)
kf(n−1),则原式变为
f
(
n
)
−
k
f
(
n
−
1
)
=
(
a
−
k
)
f
(
n
−
1
)
+
b
f
(
n
−
2
)
f(n)-kf(n-1)=(a-k)f(n-1)+bf(n-2)
f(n)−kf(n−1)=(a−k)f(n−1)+bf(n−2)
为使
f
(
n
)
−
k
f
(
n
−
1
)
f(n)-kf(n-1)
f(n)−kf(n−1) 与
f
(
n
−
1
)
−
k
f
(
n
−
2
)
f(n-1)-kf(n-2)
f(n−1)−kf(n−2) 为等比数列,需要求上式两边对应系数成比例,而这也可以用行列式表示,两行成比例等价于行列式为零,即
∣
a
−
k
b
1
−
k
∣
=
0
\left| \begin{array}{cccc}a-k & b \\1 & -k \end{array} \right|=0
∣∣∣∣a−k1b−k∣∣∣∣=0
这正是矩阵 A A A 的特征值 λ \lambda λ 需满足的方程 ∣ A − λ I ∣ = 0 |A-\lambda I|=0 ∣A−λI∣=0.
所以,此文介绍的两种方法本质上是一样的.
五、实际实现
虽然已经求出完美的通项公式,理论上将可以求得数列的任意项. 但实际上,由于通项公式中含有无理数,计算机进行计算时,是用的有限位浮点数来表示无理数,所以当指数 n n n 较大时,会产生较大的运算误差,这是我们不想要的.
上文已提到,
(
f
n
f
n
−
1
)
=
A
n
−
1
(
1
0
)
,
A
=
(
1
1
1
0
)
\begin{pmatrix}f_n\\f_{n-1}\end{pmatrix}= A^{n-1}\begin{pmatrix}1\\0\end{pmatrix},A=\begin{pmatrix}1&1\\1&0\end{pmatrix}
(fnfn−1)=An−1(10),A=(1110)
根据矩阵乘法的定义, f n f_n fn 即为 A n − 1 \small A^{n-1} An−1 首行首列的元素.
由于是整数的乘法和加法运算,所以这种方法不存在运算误差,但是需要计算 A n − 1 \small A^{n-1} An−1,下面介绍一种快速算法,能够将时间复杂度控制在 O ( log n ) \small O(\log n) O(logn) 量级.
先考虑
x
n
x^n
xn 的快速算法,将
n
n
n 利用二进制进行表示,
n
=
(
d
k
d
k
−
1
⋯
d
1
d
0
)
2
=
d
k
2
k
+
d
k
−
1
2
k
−
1
+
⋯
+
d
1
2
+
d
0
n=(d_kd_{k-1}\cdots d_1d_0)_2=d_k2^k+d_{k-1}2^{k-1}+\cdots+d_12+d_0
n=(dkdk−1⋯d1d0)2=dk2k+dk−12k−1+⋯+d12+d0
d
i
=
0
o
r
1
,
0
≤
i
≤
k
−
1
,
d
k
=
1
\small d_i=0\,or\, 1,0\leq i\leq k-1,\,d_k=1
di=0or1,0≤i≤k−1,dk=1,则
x
n
x^n
xn 可以用连乘形式进行表示.
x
n
=
x
d
k
2
k
+
d
k
−
1
2
k
−
1
+
⋯
+
d
1
2
+
d
0
=
x
d
k
2
k
x
d
k
−
1
2
k
−
1
⋯
x
d
1
2
x
d
0
x^n=x^{d_k2^k+d_{k-1}2^{k-1}+\cdots+d_12+d_0}=x^{d_k2^k}x^{d_{k-1}2^{k-1}}\cdots x^{d_12}x^{d_0}
xn=xdk2k+dk−12k−1+⋯+d12+d0=xdk2kxdk−12k−1⋯xd12xd0
考虑其中的某一项:
若
d
i
=
0
d_i=0
di=0,
x
d
i
2
i
=
1
x^{d_i2^i}=1
xdi2i=1;
若
d
i
=
1
d_i=1
di=1,
x
d
i
2
i
=
x
2
i
=
(
x
2
i
−
1
)
(
x
2
i
−
1
)
x^{d_i2^i}=x^{2^i}=(x^{2^{i-1}})(x^{2^{i-1}})
xdi2i=x2i=(x2i−1)(x2i−1).
所以具体程序可以这样来写
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;
}
上述算法是不完整的,因为没有给出 d i d_i di 的求法,给出求法后,得到
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;
}
时间复杂度为 O ( log n ) \small O(\log n) O(logn). 类比得到 A m \small A^{m} Am 的快速算法.
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