斐波那契数列前n项和 c++_斐波那契数列第一千万项怎么求

7c796eb83ddf74fd35ee551be2b56244.png

众所周知,斐波那契数列的定义是:f(0) = 0, f(1) = 1, 且当 n > 1 时 f(n) = f(n-1) + f(n-2)。今天讨论个相对简单的问题:斐波那契数列第一千万项怎么求?

暴力算法(V0)

最容易想到的是直接翻译递推式,二话不说撸出代码:

func 

很可惜当输入为 n = 10000000 时这段代码在我的电脑上跑了足足有 15 分钟,风扇呼呼地转。

矩阵快速幂优化(V1)

因为从定义我们很容易得到:

问题转成了如何快速求出 R,这里对 n 分奇偶讨论:

根据这一版的递推公式来实现的代码:

func 

当输入为 n = 10000000 时大约 2.435 秒出结果,当然我们也可以把递归改成迭代(速度没有明显差距):

func 

矩阵对称性优化(V2)

之所以写这篇文章,主要就是因为网上大部分的资料都止步于矩阵快速幂,其实在这基础上还有可以秀微操的空间。我们再来仔细看看 R 的定义:

你会发现之前的运算其实做了很多无用功:

  • z 和 y 必然相等,z 没必要再计算一遍。
  • t = x - y,因此 t 也没必要再计算一遍。

最后你会发现,原来只需要计算矩阵第一列的那两个元素即可:

根据这一版的公式再次实现代码:

func 

这次只需要 0.843 秒了,同样我们可以把递归改成迭代(速度没有明显差距):

func 

一种更慢的写法(Slow)

其实不管是V1还是V2,除了上面的递归和迭代两种写法,网上还能见到另一种写法:

func 

很不幸这种写法虽然更容易实现,但在绝大多数情况下要更慢一些,下表是各个函数在我电脑上的运行时间汇总:

d41f3c9337f65f86b58c37cfabb3299f.png

想知道为什么可以查一查秦九韶算法(Horner's method),我们原始的写法实际上是利用了这个方法进行优化的。

补充版本:Cassini’s formula(V3)

V2版本看起来似乎已经做到极致了,因为对于一个 n 它只需要执行 3*log(n) 次乘法运算(数据大到一定程度时乘法运算是主要开销)。

还能再优化吗?可以的。(受到 fss.sosei:斐波那契数列与Python的尾递归蹦床 连载【6】 的启发)

再来分析V2版本里面的 3 次核心乘法,其本质上就是:

这时候我们需要用到一个叫做 Cassini’s formula 的公式了:

证明很简单,考虑 R 矩阵的行列式就可以了,这里不多赘述。利用这个公式,我们可以进行以下推导:

也就是说,原来 xy 还可以由 xx 和 yy 得到,免去了一次乘法,基于此优化的代码如下:

func 

这段代码在 n = 10000000 时运行了 0.522 秒,比起V2版本的 0.843 秒还要好不少,当然我们也可以把递归改成迭代(速度没有明显差距):

func 


最后附上相关的辅助代码:

type 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值