斐波那契数列取模(大数)分治算法

这是算法课程上完分之策略后老师留的一道题目:

菲波那契数列如下:1,1,2,3,5,8,13,21,34......其中a[1] = 1, a[2] = 1, a[n]=a[n-1]+a[n-2](n>=3)。对给定的下标n,求解a[n]%1997的值.

其中测试数据n是整数范围内。

这个题目,主要是用到很关键的一个数学知识,斐波那契数列的求法,可以转换为矩阵的连乘,矩阵的n此方算法又可以用分治的算法。

而且又有理论依据:(n*m)%c=[ (n%c)*(m%c) ]%c  ;   (n+m)%c=[   (n%c)+(m%c)  ]%c ,所以过程中的结果可以随时取模,而不影响最终的结果

关于斐波那契数列的矩阵连乘求法如下:

我们知道我们若要简单计算f(n),有一种方法就是先保存 
a=f(0),b=f(1),然后每次设: 
a'=b b'=a+b

并用新的a'和b'来继续这一运算

如果大家熟悉利用“矩阵”这一工具的话,就知道,如果把a、b写成一个向量[a,b],完成上述操作相当于乘以矩阵 
0 1 
1 1 
也就是说,如果我们要求第100个fibonacci数,只需要将矩阵 
[0,1]乘上 
0 1 
1 1 
的一百次方,再取出第一项

因为我们知道,矩阵运算满足结合律,一次次右乘那个矩阵完全可以用乘上那个矩阵的N次方代替,更进一步,那个矩阵的N次方就是这样的形式: 
f(n-1) f(n) 
f(n) f(n+1)

而求矩阵的N次方,由于矩阵乘法满足结合律,所以我们可以用log(N)的算法求出——这个算法大家都会么? 
一个是二分,一个是基于二进制的求幂

二分的原理:要求矩阵的N次方A(N),设i=N/2若N%2==1, 则 A(N)=A(i)*A(i)*A(1)若N%2==0, 则 A(N)=A(i)*A(i)

基于二进制的原理:将N拆为二进制数,譬如13=1101那么 A^13= A^8 * A^4 * A^1 (这里^表示幂运算)

也就是说,由A^1开始,自乘得到A^2,然后自乘得到A^4,如果N对应位为1,则将这个结果乘到目标上去

这样的话,将所有乘法改为模乘,就可以得到一个较大Fibonacci数除以M的余数

若不用递归,其实类似

实现代码:

#include<iostream>
using namespace std;
// f(n)=f(i)*f(n-i-1)+f(i+1)*f(n-i)
int tempA,tempB,tempC,tempD;
void func(int n,int &a,int &b,int &c,int &d){if(n==1){a=0;b=c=d=1;return ;}if(n%2==0){func(n/2,a,b,c,d);tempA=a*a+b*c;tempB=b*(a+d);tempC=c*(a+d);tempD=c*b+d*d;a=tempA%1997;b=tempB%1997;c=tempC%1997;d=tempD%1997;return;}else{func(n/2,a,b,c,d);tempA=b*(a+d);tempB=a*a+b*(a+c+d);tempC=c*b+d*d;tempD=c*(a+b+d)+d*d;a=tempA%1997;b=tempB%1997;c=tempC%1997;d=tempD%1997;return;}
}
int main(){int n;while(cin>>n&&n!=0){int a,b,c,d;if(n<=2){cout<<1<<endl;continue;}else n-=2;func(n,a,b,c,d);cout<<(b+d)%1997<<endl;}    return 0;
}

斐波那契数列取模(大数)分治算法相关推荐

  1. Java_斐波那契数列_兔子生兔子算法

    斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10 ...

  2. 大数斐波那契数列+取余

    斐波那契序列 集锦 (转) [定理1] 标准Fibonacci序列(即第0项为0,第1项为1的序列)当N大于1时,一定有f(N)和f(N-1)互质 其实,结合"互质"的定义,和一个 ...

  3. 斐波那契数列(二)--矩阵优化算法

    之前写了一篇从斐波那契数列分析递归与动态规划(JAVA)来优化斐波那契数列,这样可以使算法的时间复杂度从O(n^2)变到O(n),这是使用递归公式f(n)=f(n-1)+f(n-2)求斐波那契数列的最 ...

  4. 算法之矩阵计算斐波那契数列

    算法之矩阵计算斐波那契数列 本节内容 斐波那契介绍 普通方式求解斐波那契 矩阵概念 矩阵求幂 矩阵求解斐波那契 1.斐波那契介绍 斐波那契数列有关十分明显的特点,那是:前面相邻两项之和,构成了后一项. ...

  5. python使用递归实现斐波那契数列

    递归简而言之就是函数自己调用自己,在python中,会自动限制调用次数防止造成内存溢出 下面时使用递归的方法实现斐波那契数列取值的代码 def fibonacci(n):if n == 1 or n ...

  6. 经典算法(6)斐波拉契数列、兔子繁殖、跳台阶算法

    写在前面: 我是「扬帆向海」,这个昵称来源于我的名字以及女朋友的名字.我热爱技术.热爱开源.热爱编程.技术是开源的.知识是共享的. 这博客是对自己学习的一点点总结及记录,如果您对 Java.算法 感兴 ...

  7. 计算斐波那契数列递归算法和非递归算法的比较

    对于斐波那契数列的计算是计算机算法经典问题,常见的算法有递归算法和非递归算法两种,那么它们之间的不同应该如何对比? 本文用python为例,比较两种不同算法的时间复杂度等不同 代码比较 递归算法: # ...

  8. 2018年东北农业大学春季校赛 K wyh的数列【数论/斐波那契数列大数取模/循环节】...

    链接:https://www.nowcoder.com/acm/contest/93/K 来源:牛客网 题目描述 wyh学长特别喜欢斐波那契数列,F(0)=0,F(1)=1,F(n)=F(n-1)+F ...

  9. ACM_无聊者序列(斐波那契数列大数取余(同余)+规律)

    Problem Description: 瓜瓜在玩着由红色和蓝色的大理石做成的玻璃珠,他将n个玻璃珠从左到右排成一个序列叫做无聊者序列.一个非空的红色和蓝色玻璃珠组成的序列是一个无聊者序列.这个序列的 ...

最新文章

  1. 新的sublime text已经上传网盘,地址写在下面
  2. AI视觉大牛朱松纯担任北大AI研究院院长,提出通过构建大任务平台走向通用AI...
  3. powerdesigner生成数据库文档
  4. Hadoop4.2HDFS测试报告之四
  5. Qt Creator添加新的自定义向导
  6. python3语音识别模块_『开源项目』基于STM32的智能垃圾桶之语音识别
  7. 实验七 不同网段的dhcp
  8. 自动化测试学习笔记(一)HTML概念
  9. JavaScript快速上手
  10. sping加载bean都发生了些什么
  11. Kettle Spoon字段拆分
  12. IllegalArgumentException,Mapped Statements collection does not contain value for xxxxx
  13. oracle.exe占用cpu太高,360tray.exe占用CPU过高,怎么办
  14. 获取设备唯一编号替代IMEI新方案
  15. 谷歌大数据三大论文中文版和英文版合集
  16. LEAK: ByteBuf.release() was not called before it's garbage-collected. Enable advanced leak reporting
  17. 硬件电子开发常用工具
  18. linux wine运行效率,Linux 使用 Wine 运行 TIM 简明教程
  19. 北海·涠洲岛攻略(两日游)
  20. k8s部署前后端分离项目

热门文章

  1. 今天下午接到阔总编的电话
  2. MapReduce基础开发之二数据去重和排序
  3. 概览屏幕(最新动态屏幕、最近任务列表)
  4. RocketMQ-- 一对多 (消费者与生产者)
  5. 计算机系统的分类与发展方向
  6. Python的安装 || python介绍
  7. 理解CSS3 transform中的Matrix(矩阵)
  8. cortex M内核优先级设置
  9. CTFshow 文件包含 web78
  10. TensorFlow下载文件到当前目录