老汉也即将面临找工作的抉择,为了不让自己死相太难看,现在打算刷刷题。都是比较粗浅,大神轻拍!
比萨的列奥纳多,又称斐波那契(Leonardo Pisano ,Fibonacci, Leonardo Bigollo,1175年-1250年),意大利数学家,西方第一个研究斐波那契数,并将现代书写数和乘数的位值表示法系统引入欧洲。
斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、……在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)
(这是老汉从百度上抄过来的,呵呵)
经过月数
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
幼仔对数
|
1
|
0
|
1
|
1
|
2
|
3
|
5
|
8
|
13
|
21
|
34
|
55
|
89
|
成兔对数
|
0
|
1
|
1
|
2
|
3
|
5
|
8
|
13
|
21
|
34
|
55
|
89
|
144
|
总体对数
|
1
|
1
|
2
|
3
|
5
|
8
|
13
|
21
|
34
|
55
|
89
|
144
|
233
|
#include <stdio.h> #define MAX 50 long long Fib_recursion(int n) { if (n == 0) return 0; else if(n == 1) return 1; else if(n > 1) return Fib_recursion(n - 1) + Fib_recursion (n - 2); else return -1; } int main(int argc, char *argv[]) { int n; long long result; while(scanf("%d", &n) != EOF) { result = Fib_recursion(n); printf("Done.After %d months, there are %lld pairs of rabbits!\n", n, result); } return 0; }
$ TIMEFORMAT="" time ./main 50如上所示,我们采用命令time进行测试,在linux上使用TIMEFORMAT变量来重置默认的posix时间输出格式。得到如下结果:
Done.After 50 months, there are 20365011074 pairs of rabbits! 120.78user 0.00system 2:03.16elapsed 98%CPU (0avgtext+0avgdata 448maxresident)k 0inputs+0outputs (0major+153minor)pagefaults 0swaps可以看出,当n=50时,这个程序需要占用98%的CPU,耗时两分钟才能跑完。效率太低了
效率太慢,除了最后一个数,每个数都被算了一遍又一遍,时间复杂度差不多是5n^2/3
复杂度,引自 啊汉的博客
#include <stdio.h> #define MAX 100 long long Fib_array(int n) { long long a[MAX], result; int i; a[0] = 1; a[1] = 1; if(n < 2) { return -1; } for(i = 2; i <= n; i++) { a[i] = a[i - 1] + a[i - 2]; } result = a[n]; return result; } int main(int argc, char argv[]) { int n; long long result; scanf("%d", &n); result = Fib_array(n); printf("Done.After %d months, there are %lld pairs of rabbits!\n", n, result); return 0; }
$ TIMEFORMAT="" time ./main 50瞬间,结果就出来了
Done.After 99 months, there are 3736710778780434371 pairs of rabbits! 0.00user 0.00system 0:01.71elapsed 0%CPU (0avgtext+0avgdata 452maxresident)k 0inputs+0outputs (0major+153minor)pagefaults 0swaps可以看出,CPU占用率为0,时间为毫秒级
空间复杂度和时间复杂度都是0(n),效率一般,比递归来得快。
复杂度,引自 啊汉的博客#include <stdio.h> long long Fib_iteration(int n) { long long result, pre_result, temp; result = pre_result = 1; while(n >= 2) { temp = result; result += pre_result; pre_result = temp; n--; } return result; } int main(int argc, char argv[]) { int n; long long result; scanf("%d", &n); result = Fib_iteration(n); printf("Done.After %d months, there are %lld pairs of rabbits!\n", n, result); return 0; }
时间复杂度是o(n),空间复杂度是o(1)。效率最高。
复杂度,引自 啊汉的博客好了,说了半天了,还没进入正题。有关斐波那契问题,以后有机会再探讨。先进入HDOJ 2044题,看题
看两个示例,来理解题目的意思
从上面的这几个例子中,可以发现这么个规律,前两次走法的和就是这一次的走法。老汉可以猜测这是个斐波那契数列;既然是斐波那契数列,那么如何确定n的值呢?
n = b - a?
看看这样行不行啊,
还真可以,行了,这就是个斐波那契数列了。有兴趣自己推一推
#include <stdio.h> #define MAX 50 int main() { /* gcc编译器,支持long long型变量 */ long long fib[MAX];//windows编译器请写为__int64 /* N为实例数量;a,b为两个蜂房编号;i,j作为循环变量*/ int N, a, b, i, j; /*len 用来保存两个蜂房的距离,作为斐波那锲数列的参数*/ int len; while (scanf("%d", &N) != EOF) { for(i = 0; i < N; i++) { scanf("%d %d", &a, &b); len = b - a; /*检查输入的正确性,如果a>b,报错*/ if(a > b) { printf("error: Wrong Data Format!\n"); break; } fib[1] = 1; fib[2] = 2; for(j = 3; j <= len; j++) { fib[j] = fib[j-1] + fib[j-2]; } printf("%lld\n", fib[b-a]); } } return 0; }
点击打开2041
一画图,一看规律,一次加一或者加二,马上发现是一个典型的二阶Fibonacci(斐波那契)数列递增规律:
每加一格楼梯就会增加两条新路线,一条连向前一格,一条连向前两格,即递增规律Fib[i]=Fib[i-1]+Fib[i-2];
#include <stdio.h> int main(int argc, char *argv[]) { int n, m; /*windows环境下请替换为__int64型*/ long long result, pre_result, temp; scanf("%d", &n); while(n--) { scanf("%d", &m); result = pre_result = 1; while(m > 2) { temp = result; result += pre_result; pre_result = temp; m--; } /*windows环境下请替换为%I64d*/ printf("%lld\n", result); } return 0; }