题目描述 Description
斐波纳契数列是这样的数列:
f1 = 1
f2 = 1
f3 = 2
f4 = 3
....
fn = fn-1 + fn-2
输入一个整数n
求fn
输入描述 Input Description
一个整数n, n<= 40
输出描述 Output Description
一个整数fn
样例输入 Sample Input
3
样例输出 Sample Output
2
数据范围及提示 Data Size & Hint
n<=40
很高兴,比起上一题,本题很能体现递推的优越性(其实pascal语言由于申请栈空间时有时间损耗,所以递推算法对于p党来说普遍优于递归算法)(RE:202也算一条吧~~)
本题既然给出了规律,那么问题其实就是根据规律依靠已知(一般是fib[1]和fib[2])求未知(fib[n])。
规律体现了这样的递推式:fib[n]=fib[n-1]+fib[n-2]
首先递归实现十分简单(这也是递归的好处,很难想出递推顺序的果断用递归骗分),不断递归直到n=1 or 2。
但是递归过程中(没有记忆化)会造成重复计算,由于计算f[n]和f[n-1]时,都用到f[n-2],然而两者的计算过程是独立进行的,所以f[n-2]就悲催地被计算了两次,每次计算都要递归到最深层。这样一来有形的时间就增加了一倍(还有上文说过的pascal缺点)。这是递推就大显身手。
如果说递归是被动索取,那么递推就是主动探索。递推由已知出发,不断把未知变成已知,直到所求的答案也变成已知。
那么为了使算过的数不被忘掉,我们需要数组来实现,不断计算fib[n],把它存在f数组的f[n]中,下次用到fib[n]时直接调用f[n]的值。
递推对pascal来说,一不爆栈,二节省时间,这是递归所没有的。
算法描述:读入n,依次计算fib[i]的值,直到i=n。输出f[n]。
Program fib; Var n,i:longint; f:array[1..100]of longint; Begin readln(n); fillchar(f,sizeof(f),0); f[1]:=1; f[2]:=1; for i:=3 to n do f[i]:=f[i-1]+f[i-2]; writeln(f[n]); End.