对数次递归计算Fibonacci数列

翻了翻博客,距上一次更新差不多快一个月了。在摸黑起床又摸黑睡觉的忙了半个月之后,又迷上了两个APP(Hunters 2Mini Motor Racing),也就懒得更新了。

今天在朋友的博客上看到一篇文章对数步计算斐波那契数列(不知为什么当时首先想到的是当年奎哥的口头禅“小技巧”,看来“中毒”颇深,呵呵!),觉得挺有意思的便来证明一下。

根据Fibonacci数列的定义,很直观的可以通过重复下面这个过程来进行计算

{aa+bba

这个过程很容易转化为矩阵形式:

(ab)(1110)(ab)

更一般的,考虑线性变换

fp,q=(p+qqqp)

显然,Fibonacci数列的每一次迭代可表示为f0,1。下面考虑一般化的情形,计算第n个Fibonacci数的过程可表示为

fn:=(fp,q)n=fffn

通过矩阵运算可知

f2=(p+qqqp)(p+qqqp)=(p2+2pq+2q22pq+q22pq+q2p2+q2)=(p'+q'q'q'p'):=fp',q'

其中{p'=p2+q2q'=2pq+q2

所以fn可分解为

fn={ffn-1if n is odd(f2)n2=fp',q'n2if n is even

于是也就有了下面这样的递归实现(这里我再转一下,不过是R的)

fibonacci <- function(n, a, b, p, q) {
  if(n==0)
    return(b)
  if(n%%2==0)
    return(fibonacci(n/2,a,b,p*p+q*q,2*p*q+q*q))
  return(fibonacci(n-1,a*p+a*q+b*q,a*q+b*p,p,q))
}
# 计算前10个数
mapply(fibonacci,n=1:10,MoreArgs=list(a=1,b=0,p=0,q=1))
 [1]  1  1  2  3  5  8 13 21 34 55

Published: May 10 2012