Fibonacci数——求第n个斐波拉契数
来源:互联网 发布:最佳作息时间 知乎 编辑:程序博客网 时间:2024/05/22 15:33
Fibonacci数——求第n个斐波拉契数
#include<iostream>#include<cmath>#include<ctime>using namespace std;time_t begin_,end_;//递归版本一long Fibonacci_rec_v1(long const n){ if (n == 1 || n == 2) return 1L; return Fibonacci_rec_v1(n-1) + Fibonacci_rec_v1(n-2);}//递归版本二 动态规划long *FibonacciNum;bool *isdone;long Fibonacci_rec_v2(long const n){ if (isdone[n]) return FibonacciNum[n]; isdone[n] = true; FibonacciNum[n] = Fibonacci_rec_v2(n - 1) + Fibonacci_rec_v2(n - 2); return FibonacciNum[n]; }//非递归版本一long Fibonacci_norec_v1(long const n){ long fnmins1(1l); long fnmins2(1l); long temp; for (int i(2); i < n; i++){ temp = fnmins1; fnmins1 += fnmins2; fnmins2 = temp; } return fnmins1;}//递归求乘方void _2x2MatrixCalc(long const a11, long const a12, long const a21, long const a22, long const c11, long const c12, long const c21, long const c22, long &b11, long &b12, long &b21, long &b22){ b11 = a11*c11 + a12*c21; b12 = a11*c12 + a12*c22; b21 = a21*c11 + a22*c21; b22 = a21*c12 + a22*c22;}//求乘方问题void M_helper(long const, long const, long const, long const, long &b11, long &b12, long &b21, long &b22, long const n){ if (n == 1){ b11 = 1, b12 = 1; b21 = 1, b22 = 0; return; } if (n % 2 == 0) { M_helper(1, 1, 1, 0, b11, b12, b21, b22, n >> 1); long t11(b11), t12(b12), t21(b21), t22(b22); _2x2MatrixCalc (t11, t12, t21, t22, t11, t12, t21, t22, b11, b12, b21, b22 ); return; } M_helper(1, 1, 1, 0, b11, b12, b21, b22, n >> 1); long t11(b11), t12(b12), t21(b21), t22(b22); _2x2MatrixCalc (t11, t12, t21, t22, t11, t12, t21, t22, b11, b12, b21, b22 ); t11 = b11, t12 = b12, t21 = b21, t22 = b22; _2x2MatrixCalc (1, 1, 1, 0, t11, t12, t21, t22, b11, b12, b21, b22 );}//非递归版本二long Fibonacci_norec_v2(long const n){ long b11, b12, b21, b22; M_helper(1,1,1,0,b11, b12, b21, b22,n-2); return b11+b12;}//非递归版本三---存在精度问题。long Fibonacci_norec_v3(long const n){ double r1 = (1 - sqrt(5))/2; double r2 = (1 + sqrt(5))/2; return (pow(r2, n - 1) + pow(r2, n - 2) - pow(r1, n - 1) - pow(r1, n - 2)) / (r2 - r1);}int main(){ long n; cout << "输入序数"<<endl; cin >> n; begin_ = clock(); cout<<"Fibonacci_rec_v1结果:"<<Fibonacci_rec_v1(n)<<endl; end_ = clock(); cout << "time:" << (double)(end_ - begin_) << "miliseconds"<<endl; begin_ = clock(); FibonacciNum = new long[n+1]; isdone = new bool[n+1]; FibonacciNum[1] = 1; FibonacciNum[2] = 1; for (int i(3); i <= n; i++)isdone[i] = false; cout << "Fibonacci_rec_v2结果:" << Fibonacci_rec_v2(n) << endl; end_ = clock(); cout << "time:" << (double)(end_ - begin_) << "miliseconds" << endl; begin_ = clock(); cout << "Fibonacci_norec_v1结果:" << Fibonacci_norec_v1(n) << endl; end_ = clock(); cout << "time:" << (double)(end_ - begin_) << "miliseconds" << endl; begin_ = clock(); cout << "Fibonacci_norec_v2结果:" << Fibonacci_norec_v2(n) << endl; end_ = clock(); cout << "time:" << (double)(end_ - begin_) << "miliseconds" << endl; begin_ = clock(); cout << "Fibonacci_norec_v3结果:" << Fibonacci_norec_v3(n) << endl; end_ = clock(); cout << "time:" << (double)(end_ - begin_) << "miliseconds" << endl; system("pause");}
算法说明:
//递归版本一long Fibonacci_rec_v1(long const n){ if (n == 1 || n == 2) return 1L; return Fibonacci_rec_v1(n-1) + Fibonacci_rec_v1(n-2);}
这个版本直接由Fibonacci的定义得到,重复计算的子问题比较多,效率非常低。
//递归版本二 动态规划long *FibonacciNum;bool *isdone;long Fibonacci_rec_v2(long const n){ if (isdone[n]) return FibonacciNum[n]; isdone[n] = true; FibonacciNum[n] = Fibonacci_rec_v2(n - 1) + Fibonacci_rec_v2(n - 2); return FibonacciNum[n]; }
这个版本是对上面那个版本的改进,用一对数组记录已经计算过了的子问题,这样就大大加快了算法的效率。
//非递归版本一long Fibonacci_norec_v1(long const n){ long fnmins1(1l); long fnmins2(1l); long temp; for (int i(2); i < n; i++){ temp = fnmins1; fnmins1 += fnmins2; fnmins2 = temp; } return fnmins1;}
fn=fn−1+fn−2 ,可以由这个公式,迭代的自低向上找到fn ,通过子问题累计到问题的解,没有重复计算的子问题,效率非常高。
//非递归版本二long Fibonacci_norec_v2(long const n){ long b11, b12, b21, b22; M_helper(1,1,1,0,b11, b12, b21, b22,n-2); return b11+b12;}
由公式
fn=fn−1+fn−2 ,可得下面的矩阵方程:
这个矩阵方程可以化为(fnfn−1)=(1110)(fn−1fn−2) 设M为(fnfn−1)=(1110)n−2(11) ,整个找第n个Fibonacci数的算法就转化为了求矩阵M。找M的算法就和数值自乘方求解的问题如出一辙,可以用递归的算法实现,还可以在递归的基础上用动态规划的方法提高求解效率,更可以用迭代的方式来求解。(1110)n−2
//非递归版本三---存在精度问题。long Fibonacci_norec_v3(long const n){ double r1 = (1 - sqrt(5))/2; double r2 = (1 + sqrt(5))/2; return (pow(r2, n - 1) + pow(r2, n - 2) - pow(r1, n - 1) - pow(r1, n - 2)) / (r2 - r1);}
可以根据矩阵对角化的公式
A=PDP−1 (其中D是对角矩阵)将A:对角化然后直接求解。(1110) An=PDnP−1 。最后得到fn=rn−12+rn−22−rn−11−rn−21r2−r1其中r1,r2是矩阵A的特征值 。
0 0
- Fibonacci数——求第n个斐波拉契数
- 求第n个Fibonacci数
- java中用递归方法求第n个Fibonacci数
- 求 Fibonacci 数第n位的位数 ~高精度
- 求第n个斐波那契(fibonacci)数
- HOJ 1864—求Fibonacci第n个数有多少位?
- 递归求fibonacci的第n项
- 求Fibonacci数列的第n项
- 求Fibonacci数列的第n项
- 求Fibonacci数量的第N项
- poj 3070 Fibonacci 【矩阵快速幂 求第N个斐波那契数%1000】
- (Relax 矩阵快速幂1.1)POJ 3070 Fibonacci(求第n个斐波那契数的后四位。n很大)
- Fibonacci序列 —— O(log n)求Fibonacci数列(非矩阵法)
- 求Fibonacci数列的第N个数字
- 九度oj1387求Fibonacci数列第n项
- 递归实现求Fibonacci数列的第n项
- 数据结构——算法之(014)( 输入n,用最快的方法求Fibonacci数列的第n项)
- 求第n个斐波拉契数
- 在线编程--用两个栈实现队列
- java编程小记
- java项目日志
- ubuntu下如何将笔记本自带的键盘关闭
- Android网络与数据存储_学习笔记_第六周:SQLite与ContentProvider
- Fibonacci数——求第n个斐波拉契数
- 在线编程--用递归函数和栈操作逆序栈
- 多分类问题中混淆矩阵(Confusion Matrix)的Matlab画法
- 适配器模式
- IP协议及IP数据报解析
- 动态规划之Palindrome
- 演示程序之打游戏 -- 慕司板IAP15
- PAT乙级1005-德才论
- 经典算法——二进制中1的个数