斐波那契数列取模(大数)分治算法
这是算法课程上完分之策略后老师留的一道题目:
菲波那契数列如下: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; }
斐波那契数列取模(大数)分治算法相关推荐
- Java_斐波那契数列_兔子生兔子算法
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10 ...
- 大数斐波那契数列+取余
斐波那契序列 集锦 (转) [定理1] 标准Fibonacci序列(即第0项为0,第1项为1的序列)当N大于1时,一定有f(N)和f(N-1)互质 其实,结合"互质"的定义,和一个 ...
- 斐波那契数列(二)--矩阵优化算法
之前写了一篇从斐波那契数列分析递归与动态规划(JAVA)来优化斐波那契数列,这样可以使算法的时间复杂度从O(n^2)变到O(n),这是使用递归公式f(n)=f(n-1)+f(n-2)求斐波那契数列的最 ...
- 算法之矩阵计算斐波那契数列
算法之矩阵计算斐波那契数列 本节内容 斐波那契介绍 普通方式求解斐波那契 矩阵概念 矩阵求幂 矩阵求解斐波那契 1.斐波那契介绍 斐波那契数列有关十分明显的特点,那是:前面相邻两项之和,构成了后一项. ...
- python使用递归实现斐波那契数列
递归简而言之就是函数自己调用自己,在python中,会自动限制调用次数防止造成内存溢出 下面时使用递归的方法实现斐波那契数列取值的代码 def fibonacci(n):if n == 1 or n ...
- 经典算法(6)斐波拉契数列、兔子繁殖、跳台阶算法
写在前面: 我是「扬帆向海」,这个昵称来源于我的名字以及女朋友的名字.我热爱技术.热爱开源.热爱编程.技术是开源的.知识是共享的. 这博客是对自己学习的一点点总结及记录,如果您对 Java.算法 感兴 ...
- 计算斐波那契数列递归算法和非递归算法的比较
对于斐波那契数列的计算是计算机算法经典问题,常见的算法有递归算法和非递归算法两种,那么它们之间的不同应该如何对比? 本文用python为例,比较两种不同算法的时间复杂度等不同 代码比较 递归算法: # ...
- 2018年东北农业大学春季校赛 K wyh的数列【数论/斐波那契数列大数取模/循环节】...
链接:https://www.nowcoder.com/acm/contest/93/K 来源:牛客网 题目描述 wyh学长特别喜欢斐波那契数列,F(0)=0,F(1)=1,F(n)=F(n-1)+F ...
- ACM_无聊者序列(斐波那契数列大数取余(同余)+规律)
Problem Description: 瓜瓜在玩着由红色和蓝色的大理石做成的玻璃珠,他将n个玻璃珠从左到右排成一个序列叫做无聊者序列.一个非空的红色和蓝色玻璃珠组成的序列是一个无聊者序列.这个序列的 ...
最新文章
- 新的sublime text已经上传网盘,地址写在下面
- AI视觉大牛朱松纯担任北大AI研究院院长,提出通过构建大任务平台走向通用AI...
- powerdesigner生成数据库文档
- Hadoop4.2HDFS测试报告之四
- Qt Creator添加新的自定义向导
- python3语音识别模块_『开源项目』基于STM32的智能垃圾桶之语音识别
- 实验七 不同网段的dhcp
- 自动化测试学习笔记(一)HTML概念
- JavaScript快速上手
- sping加载bean都发生了些什么
- Kettle Spoon字段拆分
- IllegalArgumentException,Mapped Statements collection does not contain value for xxxxx
- oracle.exe占用cpu太高,360tray.exe占用CPU过高,怎么办
- 获取设备唯一编号替代IMEI新方案
- 谷歌大数据三大论文中文版和英文版合集
- LEAK: ByteBuf.release() was not called before it's garbage-collected. Enable advanced leak reporting
- 硬件电子开发常用工具
- linux wine运行效率,Linux 使用 Wine 运行 TIM 简明教程
- 北海·涠洲岛攻略(两日游)
- k8s部署前后端分离项目