线性代数 --- 计算斐波那契数列第n项的快速算法(矩阵的n次幂)

news/2024/9/25 10:24:50/

 计算斐波那契数列>斐波那契数列第n项的快速算法(矩阵的n次幂)

The n-th term of Fibonacci Numbers:

        斐波那契数列>斐波那契数列的是一个古老而又经典的数学数列,距今已经有800多年了。关于斐波那契数列>斐波那契数列的计算方法不难,只是当我们希望快速求出其数列中的第100,乃至第1000项时,有没有又准又快的方法,一直是一个值得探讨和研究的问题。笔者(松下J27)在这篇文章中,就介绍了一种基于线性代数的快速算法,即,基于矩阵的n次幂找到斐波那契数列>斐波那契数列的第n项。这是我在MIT线性代数的公开课中看到的,并以此文记录下来。

(意大利数学家斐波那契,图片来源于参考文献【1】) 

已知斐波那契数列>斐波那契数列的数学表示方式如下:

<a class=Fibonacci:0,1,1,2,3,5,8,13,21,34......" class="mathcode" src="https://latex.csdn.net/eq?Fibonacci%3A0%2C1%2C1%2C2%2C3%2C5%2C8%2C13%2C21%2C34......" />

他始于数列的前两个初始值0,1,后面所有的项都是前两项的和,依此类推得到:

0+1=11+1=21+2=32+3=53+5=8。。。

        基于上面的计算规律,假设我用F_{i}来表示该数列的第i个数的话,那斐波那契数列>斐波那契数列用代数的方式可写成两个初值和一个递归公式的组合,即:

F_{0}=0,F_{1}=1

F_{i+2}=F_{i}+F_{i+1},\: i=0,1,2...

        现在把上面的公式用矩阵和向量的方式来表示,以便于用线性代数来分析:

1,先把初值用向量u0来表示

u_{0}=\begin{bmatrix} F_{0}\\ F_{1} \end{bmatrix}=\begin{bmatrix} 0\\ 1\end{bmatrix}

2,用向量u_{i}表示数列中的第n项。

 u_{i}=\begin{bmatrix} F_{i}\\ F_{i+1} \end{bmatrix}

3,如此一来根据递归公式就能写出第i+1项u_{i+1}

u_{i+1}=\begin{bmatrix} F_{i+1}\\ F_{i+2} \end{bmatrix}=\begin{bmatrix} F_{i+1}\\ F_{i}+F_{i+1} \end{bmatrix}

4,用矩阵来表示从第i项u_{i}到第i+1项u_{i+1}的过程

u_{i+1}=\begin{bmatrix} F_{i+1}\\ F_{i+2} \end{bmatrix}=\begin{bmatrix} F_{i+1}\\ F_{i}+F_{i+1} \end{bmatrix}=\begin{bmatrix} 0 &1 \\ 1& 1\end{bmatrix}\begin{bmatrix} F_{i}\\ F_{i+1} \end{bmatrix}=\begin{bmatrix} 0 &1 \\ 1& 1\end{bmatrix}u_{i}

其中,参与计算的矩阵A为:

A=\begin{bmatrix} 0& 1\\ 1&1 \end{bmatrix}

         现在,我们知道了初始向量u_{0},也知道如果计算u_{i+1},我们就能通过线性代数中矩阵与向量的计算来计算斐波那契数列>斐波那契数列中的任意一项:

        可以看到,如果你要计算第100项,不出意外,只要把上述步骤继续下去一定能够找到。另外,如果把上述计算中的三次计算合成一部,就是三个矩阵A连续相乘后,再乘以u0。

        这就是说,斐波那契数列>斐波那契数列中第n项的计算公式应该是:

u_{n}=A\cdot A\cdot A\cdot A...\cdot Au0=A^{n}u0

u_{n}=A^{n}u0 (式1) 

这里要注意的是,根据这种方法算出来的是一个向量,而我们需要的结果,即,第n项是该向量中的第一个元素。


引入矩阵的对角化:

        熟悉线性代数的朋友看到A的n次幂时,马上就会想到是否可以通过特征向量矩阵X特征值矩阵\Lambda对A进行对角化。

线性代数 --- 矩阵的对角化以及矩阵的n次幂-CSDN博客文章浏览阅读1k次,点赞15次,收藏9次。本文从矩阵A的对角化开始,一直聊到了对角化的应用,并以一个A的n次幂为例子结尾。https://blog.csdn.net/daduzimama/article/details/138088128

因为,如果方阵A可以被对角化为:

A=X\Lambda X^{-1}

那么上面推导出来的斐波那契数列>斐波那契数列的第n项的计算公式就能简化为:

u_{n}=A\cdot A\cdot A\cdot A...\cdot Au0=A^{n}u0\Rightarrow

u_{n}=(X\Lambda X^{-1})\cdot (X\Lambda X^{-1})\cdot (X\Lambda X^{-1})...\cdot (X\Lambda X^{-1})u0=X\Lambda ^{n}X^{-1}u0

u_{n}=X\Lambda ^{n}X^{-1}u0 , (式2) 

 

现在我们试着用(式2)去计算斐波那契数列>斐波那契数列的第100项:

第一步,计算矩阵A的特征向量与特征值:

\lambda _{1}=-0.61803399,x_{1}=\begin{bmatrix}-0.85065081 \\ 0.52573111\end{bmatrix}

\lambda _{2}=1.61803399,x_{2}=\begin{bmatrix}-0.52573111\\ -0.85065081\end{bmatrix}

 通过计算得出了两个不同的特征值,说明矩阵A可以对角化。

第二步,构建特征向量矩阵X,特征值矩阵\Lambda和特征向量矩阵的逆:

X=\begin{bmatrix} -0.85065081&-0.52573111 \\ 0.52573111&-0.85065081 \end{bmatrix}

\Lambda =\begin{bmatrix} -0.61803399 &0 \\ 0 & 1.61803399 \end{bmatrix}

 X^{-1}=\begin{bmatrix} -0.85065081&0.52573111 \\ -0.52573111&-0.85065081 \end{bmatrix}

第三步,计算特征值矩阵\Lambda的100次幂:

 \Lambda ^{100}=\begin{bmatrix} -0.61803399^{100} &0 \\ 0 & 1.61803399^{100} \end{bmatrix}

=\begin{bmatrix}1.26251334E-21 &0 \\ 0 & 7.92070840E+20 \end{bmatrix}

第四步,基于(式2)去计算第100项的值:

 u_{100}=\begin{bmatrix} 3.54224848E+20\\ 5.73147844E+20 \end{bmatrix}

其中,第100项的值为:

F_{100}=3.54224848E+20

进一步简化:

如果我能把u0表示成所有特征向量的线性组合的话,就能更进一步简化计算:

u_{0}=c_{1}x_{1}+c_{2}x_{2}...+c_{n}x_{n}=Xc (式3) 

其中,权重系数向量c等于:

c=X^{-1}u_{0} (式4) 

如此一来,斐波那契的第n项的计算公式(式1)就变成了:

u_{n}=A^{n}(c_{1}x_{1}+c_{2}x_{2}...+c_{n}x_{n})=c_{1}A^{n}x_{1}+c_{2}A^{n}x_{2}...+c_{n}A^{n}x_{n} (式5) 

 又因为这里的x都是特征向量,根据特征向量的性质,我们有Key Equation:

Ax=\lambda x

对于上式中的第一项c_{1}A^{n}x_{1}有:

c_{1}A^{n}x_{1}=c_{1}A\cdot A...\cdot A\cdot Ax_{1}=c_{1}A\cdot A...\cdot A\cdot \lambda _{1}x_{1}

因为\lambda _{1}是一个系数,所以我们把他提到前面去:

c_{1}A^{n}x_{1}=c_{1}\lambda _{1}A\cdot A...\cdot Ax_{1}

这样一来又出现了一个\lambda _{1},继续:

c_{1}A^{n}x_{1}=c_{1}\lambda _{1}A\cdot A...\cdot \lambda _{1}x_{1}

如此反复,一直到第n个乘法:

c_{1}A^{n}x_{1}=c_{1}\lambda _{1}^{n}A

依此类推,(式5)可改写成:

u_{n}=c_{1}\lambda _{1}^{n}x_{1}+c_{2}\lambda _{2}^{n}x_{2}...+c_{n}\lambda _{n}^{n}x_{n} (式6) 

 (式6) 也可以写成:

u_{n}=c_{1}\lambda ^{n}x_{1}+c_{2}\lambda ^{n}x_{2}...+c_{n}\lambda ^{n}x_{n}=X\Lambda ^{n}c (式7) 

这一点也可以通过把 (式3)代入(式2)得到(式7)

u_{n}=X\Lambda ^{n}X^{-1}u0=X\Lambda ^{n}X^{-1}(Xc)=X\Lambda ^{n}c

这里面最重要的是(式6),因为他把计算分离开了,分成了一个个常数与向量的乘积之和。

现在针对这一简化算法做一个小结,并以求斐波那契的第100项为例:

第一步,优先使用(式4)算出权重向量c

c=X^{-1}u_{0}=\begin{bmatrix} 0.52573111\\ -0.85065081 \end{bmatrix} 

\Rightarrow c_{1}=0.52573111, c_{2}=-0.85065081 

 

第二步,分别计算c_{1}\lambda _{1}^{100}x_{1}c_{2}\lambda_{2} ^{100}x_{2},其中c和\lambda都是常数。

 

第三步,求和。把第二步的结果加在一起,求出最终的结果。在本例中,因为c_{1}\lambda _{1}^{100}x_{1}中的元素几乎为0,所以他们二者的和几乎约等于c_{2}\lambda_{2} ^{100}x_{2}

u_{100}=c_{1}\lambda _{1}^{100}x_{1}+c_{2}\lambda _{2}^{100}x_{2}=\begin{bmatrix} F_{100}\\ F_{101} \end{bmatrix}

最终,得到了同样正确的结果:

F_{100}=3.54224848E+20


 (全文完) 

--- 作者,松下J27

参考文献(鸣谢):

1,https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91

2, Lec22_对角化和矩阵乘幂_哔哩哔哩_bilibili

(配图与本文无关) 

版权声明:所有的笔记,可能来自很多不同的网站和说明,在此没法一一列出,如有侵权,请告知,立即删除。欢迎大家转载,但是,如果有人引用或者COPY我的文章,必须在你的文章中注明你所使用的图片或者文字来自于我的文章,否则,侵权必究。 ----松下J27


http://www.ppmy.cn/news/1445351.html

相关文章

Slave SQL线程与PXB FTWRL死锁问题分析

1. 问题背景 2.27号凌晨生产环境MySQL备库在执行备份期间出现因FLUSH TABLES WITH READ LOCK未释放导致备库复制延时拉大&#xff0c;慢日志内看持锁接近25分钟未释放。 版本&#xff1a; MySQL 5.7.21PXB 2.4.18 慢查询日志&#xff1a; 备份脚本中的备份命令&#xff1a;…

Android数据恢复:如何在手机上恢复丢失的文件和照片

我们都有 我们错误地从手机中删除重要内容的时刻。确实如此 不一定是我们的错。其他人可以对您的手机数据执行此操作 有意或无意。这在某个时间点发生在我们所有人身上。 但是&#xff0c;今天市场上有各种各样的软件可以 帮助恢复已删除的文件。这些类型的软件被归类为数据恢复…

在HTML中使用JavaScript实时显示当前日期和时间(结尾完整例程)

在Web开发中&#xff0c;经常需要在网页上显示当前的日期和时间。HTML本身并不具备这样的动态功能&#xff0c;但我们可以借助JavaScript来实现。JavaScript是一种常用的前端脚本语言&#xff0c;它可以轻松地获取系统时间&#xff0c;并将其插入到HTML元素中。 下面是一个简单…

opencv-基本操作

本篇文章&#xff0c;我们将聊一聊利用opencv进行的一些基本操作&#xff0c;以便后续我们利用opencv进行更加复杂的处理。 1、图像的读取、显示与保存 opencv中利用cv2.imread读取RGB图像&#xff0c;利用cv2.imshow() 进行图像的显示。 # 注意: cv2.imread读取RGB图像时, 返回…

TCP、UDP客户端

TCP客户端 #include <mystdio.h> #define CLI_PORT 6666 #define CLI_IP "192.168.124.210" int main(int argc, const char *argv[])//argv[1] IP argv[2] 端口号 { if(argc <3) { printf("请在命令传参端口号和IP地址\n");…

《python编程从入门到实践》day16

昨日知识点回顾 从模块中导入类/模块 今日知识点学习 第十章 文件和异常 10.1 从文件中读取数据 10.1.1 读取整个文件 txt文件与程序文件在同一级目录 with open(pi_digits.txt) as file_object:contents file_object.read() print(contents)# 运行结果&#xff1a; # 3.1…

大数据学习笔记11-Hadoop基础2

一: 分布式的基础架构分析[重要] 集群架构模式: 主从架构(中心化): 主角色 master: 发号施令,负责任务的接受和分配 从角色 slave: 负责干活 主备架构:可以解决中心化存在的问题 主角色active : 正常工作 备角色standby : 观察主角色工作,并实时备份主角色数据,当主角色宕机…

海外http代理中的有效连通率是什么意思?

随着互联网的发展&#xff0c;许多人需要使用代理服务器来访问海外网站或绕过地理限制&#xff0c;在选择一个可靠的海外HTTP代理时&#xff0c;了解其有效连通率是至关重要的。 本文将解释有效连通率的含义&#xff0c;并提供详细的测试步骤&#xff0c;帮助您评估一家IP代理…