这是算法课程上完分之策略后老师留的一道题目:
菲波那契数列如下: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; }
相关推荐
斐波那契数列的三种算法,算法一:递归 #include #include long int fibo(int n) { if(n==0) return 0; if(n==1) return 1; return fibo(n-1)+fibo(n-2); } void main() {
Fibonacci数列斐波那契数列PPT学习教案.pptx
斐波那契数列: 在数学上它以递归的方式进行定义,指这样的一个数列:0、1、1、2、3、5、8、13、21、34、55、89、144……,即前两个数为分别为0和1,从第3项开始,每项的值都等于其前两项之和。斐波那契数列Fib(n)用...
使用C++非递归实现fibonacci数列,对正在学习算法的同学应该挺有帮助的
C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++斐波那契数列C++...
一 生小兔问题引起的二 它们也产生斐波那契数列三 通项的其他表达式四 斐波那契数列是二阶循环数列五 斐波那契数列的数论性质六 斐波那契数列的其他性质七 某些斐波那契数列之和八 斐波那契数列与连分数九 斐波那契...
用递推算法 迭代算法 公式法计算求第N个Fibonacci数,计算机能算出最大Fibonacci时N的值,计算1分钟内能计算几个Fibonacci,用公式法计算Fibonacci,当出现错误时,N为多少。
本代码使用C++语言书写,编译环境VS2013。...斐波那契数列(Fibonacci Sequence)又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、…… 本代码是练习作品,如有错误或修改,请指正,感谢感谢。
递归方法实现斐波那契数列
【问题描述】编写函数f,功能是用递归的方法求斐波那契数列的第n项,函数原型为 int f(int n),在主函数中输入一个正整数n,调用函数f求出斐波那契数列的第n项,并在主函数中输出。 斐波那契数列:1,1,2,3,5,8,13,...
递归方法 def fibonacci(n): if n <= 1: return n else: return fibonacci(n-1) + fibonacci(n-2) n = int(input("请输入要计算的斐波那契数列的项数:")) print("斐波那契数列的第", n, "项为:", fibonacci(n)) 2...
斐波那契数列(肥不拉几数列)斐波那契数列(肥不拉几数列)斐波那契数列(肥不拉几数列)斐波那契数列(肥不拉几数列)斐波那契数列(肥不拉几数列)斐波那契数列(肥不拉几数列)斐波那契数列(肥不拉几数列)...
斐波那契数列大家都很熟悉吧,咱们在高中学数学的时候,老师会讲这个定律以及算法,其实数据结构和数学息息相关,数学思维好的往往逻辑思维就比较好,今天小猿圈带大家学习一下python的斐波那契数列的实现。...
里面是【斐波那契数列】的前100项,可以当做学习过程中对照是否正确等使用,加油!
斐波那契数列算法分析.doc
【C++】斐波那契数列应用的一个实例。这是关于斐波那契数列的一个例子,用C++语言实现
汇编语言,两种方法计算斐波那契数列的前22项,斐波那契数列,分别用两种方法:递归调用,普通循环加法,使用DOSBox验证
自斐波那契数列创立以来,它在数学理论和应用上不断显露出至关重要的地位。随着时代的进步,数学家们发掘了其中的数学联系。这无疑地激发了人们进一步探索数学的兴趣,也使人们对数学的了解更加的系统化。斐波那契...
编写一个Java程序,用于输出Fibonacci数列的前20项。
经典斐波那契数列的算法实现教案.doc