《编程之美》读书笔记08:2.9 Fibonacci序列

计算Fibonacci序列最直接的方法就是利用递推公式 F(n+2)=F(n+1)+F(n)。而用通项公式来求解是错误的,用浮点数表示无理数本来就有误差,经过n次方后,当n相当大时,误差能足够大到影响浮点数转为整数时的精度,得到的结果根本不准。

用矩阵来计算,虽然时间复杂度降到O(log n),但要用到矩阵类,相当麻烦。观察:

F(n+2)=F(n)+F(n-1)=2*F(n-1)+F(n-2)=3*F(n-2)+2*F(n-4)

用归纳法很容易证明 F(n) = F(k)*F(n+1-k) + F(k-1)*F(n-k),利用该递推公式和原递推公式,要计算F(n),只要计算F([n/2])和F([n/2]+1),时间复杂度为 O(lg n)。如:要计算F(58),由 58 -> 29,30 -> 14,15 -> 7,8 -> 3,4 -> 1,2 可知只要算5次。可以用一个栈保存要计算的数,实际上,将n的最高位1(假设在第k位)左边的0去除掉后,第m次要计算的数是第k位到第k-m+1位这m个位组成的值t(m),则第m-1次要计算的数为t(m-1),且

t(m)=2*t(m-1)+(第k-m+1位是否为1)。

若第m-1次计算得到了f(k)和f(k+1),则第m次计算:

第k-m+1位

已计算

待计算

1

f(k)

f(k+1)

f(2*k+1),f(2*k+2)

0

f(2*k),f(2*k+1)

具体公式见下面代码。

下面是计算F(n)最后四位数(某道ACM题)的代码。

/*   Fibonacci数列第N个数的最后4位数
    注意,当 N>93 时 第N个数的值超过64位无符号整数可表示的范围。
F(n+2)=F(n)+F(n-1) F(0)=0 F(1)=1  F(2)=1        ==>
F(n)=F(k)*F(n+1-k) + F(k-1)*F(n-k)              ==>
F(2*n)=F(n+1)*F(n)+F(n)*F(n-1)=(F(n+1)+F(n-1))*F(n)=(F(n+1)*2-F(n))*F(n)
F(2*n+1)=F(n+1)*F(n+1)+F(n)*F(n)
F(2*n+2)=F(n+2)*F(n+1)+F(n+1)*F(n)=(F(n+2)+F(n))*F(n+1)=(F(n+1)+F(n)*2)*F(n+1)
 */

unsigned fib_last4( unsigned num)
{
  if ( num == 0 ) return 0;
  const unsigned M=10000;
  unsigned ret=1,next=1,ret_=ret;
  unsigned flag=1, tt=num;
  while ( tt >>= 1) flag <<= 1;
  while ( flag >>= 1 ){
    if ( num & flag ){
      ret_ = ret * ret + next * next;
      next = (ret + ret + next) * next;
    } else {
      //多加一个M,避免 2*next-ret是负数,造成结果不对
      ret_ = (next + next + M - ret) * ret;
      next = ret * ret + next * next;
    }
    ret = ret_ % M;
    next = next % M;
  }
  return ret;
}

转载于:https://www.cnblogs.com/flyinghearts/archive/2011/03/22/1991983.html

《编程之美》读书笔记08:2.9 Fibonacci序列相关推荐

  1. 编程之美 - 读书笔记 - 卖书折扣问题的贪心解法

    <编程之美>读书笔记(四):卖书折扣问题的贪心解法 每 次看完<编程之美>中的问题,想要亲自演算一下或深入思考的时候,都觉得时间过得很快,动辄一两个小时,如果再把代码敲一遍的话 ...

  2. 【编程之美/读书笔记】Chapter 1 游戏之乐

    这里就不写每个问题的题目了,只是记录一下自己的总结和心得. 1.1 让CPU占用率听你指挥 这个题目我刚接触的想法是和多核多线程要扯上关系的,因为自己写个死循环只能跑到CPU 35%左右的占用率,但是 ...

  3. Java并发编程之美读书笔记-并发编程基础2

    2019独角兽企业重金招聘Python工程师标准>>> 1.线程的通知与等待 Java中的Object类是所有类的父亲,鉴于继承机制,Java把所有类都需要的方法放到了Object类 ...

  4. 编程之美读书笔记2.1—求二进制数中1的个数

    解法一: 可以举一个8位二进制的例子.对于二进制操纵,我们除以一个2,原来数字就会减少一个0(向右移一位).如果除的过程中有余,那么久表示当前位置有一个1. 以10100010为例: 第一次除以2时, ...

  5. 编程之美--读书笔记--返回一个数组中所有元素被第一个元素除的结果

    笔试题目1:写一个函数,返回一个数组中所有元素被第一个元素除的结果 很多人会想到如下: void DivAarry(int *pArray,int size) { for(int i=size-1;i ...

  6. 编程之美读书笔记之-高效率的安排见面会

    问题一: n个同学,分别对m个招聘见面会感兴趣.为了满足所有学生的要求,hr希望让每个同学都能参加自己所有感兴趣的见面会.然后每个见面会的时间为t.问如何安排见面会能够使得所有见面会总的时间最短. 建 ...

  7. 中国象棋将帅问题java_编程之美读书笔记1.2——中国象棋将帅问题

    http://blog.csdn.net/pipisorry/article/details/36380669 问题:下过中国象棋的朋友都知道,双方的"将"和"帅&quo ...

  8. 编程之美 - 读书笔记 - 烙饼问题与搜索树

    前 面已经写了一些关于烙饼问题的简单分析,但因为那天太累有些意犹未尽,今天再充实一些内容那这个问题研究透.我想,通过这篇文章,我们就可以把这一类问题 搞懂.再遇到优化问题,如果我们想不到别的办法,就可 ...

  9. 编程之美读书笔记_1.1_让CPU占用率曲线听你指挥

    题目:写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率.程序越精简越好,计算机语言不限.例如,可以实现下面三种情况:   1.    CPU的占用率固定在50 ...

最新文章

  1. Android 图片放错位置会拉伸变形
  2. [转]CSS3 transform顺序问题
  3. C语言标准库函数getenv的实现
  4. docker几个基础命令及nodejs容器
  5. 基本的maven的命令行命令
  6. Redis:14---常用功能之(Pipeline)
  7. mysql因计算机丢失vcr_Missvcr100.dll丢失的原因和快速修复解决方案
  8. 2021最新SSM博客,功能完善,初云博客增强版
  9. 自动无刷电机和螺旋桨测试-如何测试无人机的动力系统?
  10. 电驴搜索服务器正在连接,电驴连接不上服务器导致无法搜索解决的方法介绍
  11. git 配置winmerge
  12. 计算机主机光盘故障,光盘放进电脑里打开了显示函数不正确是什么问题?怎么处理?...
  13. 在微信群如何使用接龙功能
  14. AWS实例3T磁盘初始化分区及docker环境部署
  15. 路飞学城-Python爬虫实战密训-第1章
  16. 【ffmpeg】音频重采样
  17. java用户权限管理与角色设置(一)
  18. 代码签名是如何工作的,为什么需要代码签名?
  19. 魅族u20怎么刷Android,魅族魅蓝U20怎么刷机
  20. DHCP option43配置方法

热门文章

  1. 洛谷 P1219 八皇后
  2. 【代码笔记】iOS-长条label
  3. HackerRank Week of Code 26
  4. linux 信号处理
  5. Mysql 字符串处理函数
  6. 一个指针的引用引发的血案
  7. 保存GNOME桌面环境中声卡的音量设置
  8. 湖北宜昌:老太不慎落入江中 小伙奋勇救人
  9. Java并发工具类(闭锁CountDownLatch)
  10. 理解、学习与使用Java中的Optional