关于 斐波那契数列 的引申
来源:互联网 发布:java重载的条件 编辑:程序博客网 时间:2024/04/29 15:08
最基本的函数模型是:
/ 0 n=0
f(n)= 1 n=1
\ f(n-1)+(f-2) n>1
1.我们一般的解法是:
int fun( int n ){ if ( 0 == n ) { return0; } elseif ( 1 == n ) { return1; } else { returnfun(n - 1) + fun(n - 2); }}
2.但是递归在大的数据的情况下可能超时( 特别是在OJ上的时候 )
那么我们想想还可以用:
#include <stdio.h> int main(){ long long f[51] = { 0, 1 }; long long n, a0 = 0, a1 = 1; int i; for( i = 2; i <= 50 ; i++ ) { f[i] = a0 + a1; // 此处只要遍历一次就ok a0 = a1; a1 = f[i]; } while( scanf("%d", &n) != EOF ) // 我们可以得到任意的n的 Fibonacci 结果 { printf("%lld\n", f[n]); } return 0;}
3.算法导论上的Naive recursive squaring method 方法:其实也就是将其化成数学问题解决!
Fibonacci的一条性质是:求N项的公式是有的,即:黄金比Q的N次方/根号5 即: pow( Q, N )/sqrt( 5 )
得到最近的一个整数,那么就是第N项的 Fibonacci 数值! ( Q = ( sqrt(5) + 1 ) / 2 是黄金比 )
那么求前15项的代码如下:
#include <stdio.h>#include <math.h>int main(){ int i; double Q = 1.0 * ( 1 + sqrt( 5 ) ) / 2.0, t; for( i = 1; i < 15; i++ ) { t = pow( Q, i )/sqrt(5); // 取最近的整数就是第你项的fibonacci元素 if( (t - (int)t) < ( ( (int)t + 1 ) - t ) ) // 这个if是判断到底是那个整数近( 例如:1.3 离1近呢还是离2近 ) { printf("%d ", int(t)); } else { printf("%d ", int(t) + 1); } } getchar(); return 0;}
实际我们知道,由于计算机的浮点数的位置限制,那么我们在做上面的算式时候,当N很大的时候,很多的位可能会丢失,那么所求的结果就是不准确的,所以理论上的意义会更大!实际编程时候,当N很大的时候实不可取的~
那么下面的办法就很重要了~
4.此处还要介绍一个非常好的办法:利用矩阵
Fibonacci 说白了就是一个递推序列,f( n ) = f( n - 1 ) + f( n - 2 );
变形一下有: f( n ) = 1 *f( n - 1 ) + 1 * f( n - 2 );
那么使用矩阵表示就是:( 注意:下面表示的不好看,其实是矩阵表示,见谅! )
| f( n ) | | 1 1 | | f( n-1 ) |
| f( n-1 ) | = | 1 0 | * | f( n-2 ) |
即:
| f( n ) | | 1 1 | | f( 1 ) |
| f( n-1 ) | = | 1 0 | ^( n-1 ) * | f( 0 ) |就是那个| 1 1 |
| 1 0 | 的n-1次方后 乘以 初始化的两个数就是!
#include <stdio.h> long long all[71]; void fun( int n ){ int i; long long mat[2][2] = { 1, 0, 0, 1 }; // 单位矩阵 long long tmp[2][2]; for( i = 2; i <= n; i++ ) { tmp[0][0] = mat[0][0]; tmp[0][1] = mat[0][1]; tmp[1][0] = mat[1][0]; tmp[1][1] = mat[1][1]; mat[0][0] = tmp[0][0] + tmp[0][1]; mat[0][1] = tmp[0][0]; mat[1][0] = tmp[1][0] + tmp[1][1]; mat[1][1] = tmp[1][0]; all[i] = mat[0][0] * all[1] +mat[0][1] * all[0]; }} int main(){ int n; all[0] = 0; all[1] = 1; fun( 70 ); while( scanf("%d", &n) != EOF) { if( n == 0 ) { printf("0\n"); } else if( n == 1 ) { printf("1\n"); } else { printf("%lld\n",all[n]); } } return 0;}
关于 Fibonacci 的变体:
1》青蛙跳台阶问题:
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
分析:
当n =1, 只有1中跳法;当n =2时,有2种跳法;当n = 3 时,有3种跳法;当n = 4时,有5种跳法;当n = 5时,有8种跳法
所以还是Fibonacci 序列,只不过初始化为:f(1) = 1; f(2) = 2;
#include <stdio.h> long long all[71]; void fun( int n ){ int i; long long mat[2][2] = { 1, 0, 0, 1 }; // 单位矩阵 long long tmp[2][2]; for( i = 3; i <= n; i++ ) { tmp[0][0] = mat[0][0]; tmp[0][1] = mat[0][1]; tmp[1][0] = mat[1][0]; tmp[1][1] = mat[1][1]; mat[0][0] = tmp[0][0] + tmp[0][1]; mat[0][1] = tmp[0][0]; mat[1][0] = tmp[1][0] + tmp[1][1]; mat[1][1] = tmp[1][0]; all[i] = mat[0][0] * all[2] +mat[0][1] * all[1]; }} int main(){ int n; all[0] = 0; all[1] = 1; all[2] = 2; fun( 70 ); while( scanf("%d", &n) != EOF) { if( n == 0 || n == 1 ) { printf("1\n"); } else { printf("%lld\n",all[n]); } } return 0;}
或者代码为:
( 下面的代码计算大的数的时候可能超时,不建议 )
#include <stdio.h> int count; void fun( int s, int i, int n ){ s += i; if( s == n ) { count++; return; } else if( s > n ) { return; } else // 此处分叉 { fun( s, 1, n ); fun( s, 2, n ); }} int main(){ int n; while( scanf("%d", &n) != EOF) { count = 0; fun( 0, 0, n ); printf("%d\n", count); } return 0;}
2》 跳台阶问题(变态跳台阶)
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法
分析:
/ 1 n=1
f(n)= 2 n=2
\ f(n-1)+(f-2) n>2
#include <stdio.h> int main(){ long long f[51] = { 0, 1, 2 }; long long n = 3, sum = 3; int i; for( i = 3; i <= 50 ; i++ ) { f[i] = sum + 1; sum += f[i]; } while( scanf("%d", &n) != EOF ) { printf("%lld\n", f[n]); } return 0;}
3》 矩形覆盖
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
分析:
同上!( 说到底还是其变形 )#include <iostream> using namespace std; int main() { long long f[71]; int i; int n; f[0] = 1; f[1] = 1; for( i = 2; i <= 70; i++ ) { f[i] = f[i-1] + f[i-2]; } while( cin >> n ) { cout << f[n] << endl; } return 0; }
- 关于 斐波那契数列 的引申
- 怎么得到斐波那契数列?(m*n大小的矩形,从左上角走到左下角有多少种走法?包括一些引申题以及总结)
- 关于斐波那契数列的算法比较
- 关于斐波那契数列的复杂度最低算法
- 关于斐波那契数列的几种解法
- 关于斐波那契数列的改进
- 关于斐波那契数列的优化
- 关于斐波那契数列的性质及其应用
- 关于斐波那契数列的一些总结
- python 关于斐波那契数列的递归思路
- 关于斐波那契数列的一些例题
- 关于斐波那契数列的Java编程
- 关于斐波那契数列递归
- 关于斐波那契数列小结
- 关于斐波那契数列
- [ACM]斐波那契数列对应的奇偶数列
- 斐波那契数列数列的实现
- 有趣的斐波那契数列
- Set the Repository Path of NuGet
- Android 获得软键盘状态
- HDU 1257 (最大上升子序列)
- RFS的web自动化验收测试——第12讲 List Variables-List变量及其用法
- 备份Oracle数据库的一张表--工作小记
- 关于 斐波那契数列 的引申
- backtrack5 r3 中 "enable universe component"
- 1000!(1000的阶乘)中有几个2-----三个数组
- LPC11C14__uCOS-II V2.91 移植笔记(三)
- 使用live555 streaming media建立RTSP串流伺服器
- RFS的web自动化验收测试——第13讲 分支与循环的用法
- 标签中有js 函数
- 程序员奶爸写给天才宝宝的诗
- 使用qsort进行排序