使用矩阵快速幂计算斐波拉契数列

一.题目:

已知F[n]=F[n-1]+F[n-2],F[1]=1,F[2]=1,求给定n的F[n]

二. 思路

常见的方法就是动态规划,这样时间的复杂度为O(n)

还有一种更快速的方法:矩阵的快速幂

给出的递推式可以看做状态转移矩阵,可以表示为: 

\begin{bmatrix} F[n]\\F[n-1] \end{bmatrix} = {\begin{bmatrix} 1 &1 \\ 1 & 0 \end{bmatrix}}\begin{bmatrix} F[n-1]\\F[n-2] \end{bmatrix}

那么F[n]和F[0],F[1]的关系可以表示为

\begin{bmatrix} F[n]\\F[n-1] \end{bmatrix} =\begin{bmatrix} 1 &1 \\ 1& 0 \end{bmatrix}^{^{n-1}} \begin{bmatrix} F[0]\\F[1] \end{bmatrix}

如何暴力求解转移矩阵的n-1方,求矩阵的次数为n-2次,每次两两矩阵相乘的复杂度为2*2*2,也就是时间复杂度为O(8*n)

反而比动态规划高了

这里就用到求矩阵快速幂的方法,将时间的复杂度降到O(8logn)

矩阵快速幂就是:比如我求解上面矩阵

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

的7次方幂T^7,因为用于动态规划的转移矩阵T都是方阵(好好想一下为什么),T^2之后还是维度不变的方阵,比如T的维度是2*2,那么T^2的维度还是2*2,也就是说维度不会随着幂的增加而增加,所以对于7次方,我们分解成:(((T^2)*T)^2)*T

也就是将幂7分解成(2+1)*2+1

这样的话求解矩阵乘的次数变成了4,这样的话总的求解矩阵乘法次数N满足logn<N<2logn(想一想为什么),时间复杂度还是O(logn)级别

三.Python实现如下

import time
def mat_mul(T1,T2):
    n=len(T1)#结果的行数
    m=len(T2[0])#结果的列数
    res=[[0 for i in range(m)] for j in range(n)]
    for i in range(n):
        for j in range(m):
            res[i][j]=sum([T1[i][k]*T2[k][j] for k in range(len(T1[0]))])
    return res
def Fbi(n):
    start = time.clock()
    c=[[1,1],[1,0]]
    res=[[1,1],[1,1]]
    if 0<n<3:
        return 1
    n=n-2
    while n:
        
        if n%2:
            res=mat_mul(res,c)
        c=mat_mul(c,c)
        n=n>>1
    
    res=mat_mul(res,[[1],[1]])
    elapsed = (time.clock() - start)
    print("Time used:",elapsed)
    return res[0][0]

参考链接:

讲的非常详细,基础:

https://blog.csdn.net/yu121380/article/details/79900385

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

skj1995

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值