题目1387 斐波拉契数列
原题链接:http://ac.jobdu.com/problem.php?pid=1387
题目描述:实现最基本的斐波那契数列。
注意:
- 首先想到的就是递归,但是递归是超时的。此时需要将递归写成循环的形式。
- 斐波那契数列的第70个,已经是很大很大的数据了,long int 根本不够,应该使用 long long 类型。
- 递归的题目,一定将结果都存在数组中,根据下标输出。千万不要根据一个输入再去计算。
#include<stdio.h>
#include<stdlib.h>
int main(){
int n;
long long ans[71];
ans[0] = 0;
ans[1] = 1;
for(int i=2; i<71; i++)
{
ans[i] = ans[i-1] + ans[i-2];
}
while(scanf("%d", &n) != EOF)
{
printf("%lld\n", ans[n]);
}
return 0;
}
题目1388 跳台阶
原题链接:http://ac.jobdu.com/problem.php?pid=1388
题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
算法描述:反向思维,思考青蛙跳的最后一步。
- 青蛙最后跳一步,即 n = (n-1) + 1,则等于青蛙跳 (n-1) 级台阶的跳法。
- 青蛙最后跳两步,即 n = (n-2) + 2,则等于青蛙跳 (n-2) 级台阶的跳法。
最后得出,满足 f(n) = f(n-1) + f(n-2) 的斐波那契表达式。
此题还有变种,即一只青蛙一次可以跳上1级台阶,也可以跳上2级,还可以跳上3级。那么就满足 f(n) = f(n-1) + f(n-2) + f(n-3)。以此类推。
题目1389 变态跳台阶
原题链接:http://ac.jobdu.com/problem.php?pid=1389
题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
算法描述:
好吧,其实我是找规律做出来的……我非常逗比地没有想到使用斐波那契思想。而是发现了 f(n) = 2^(n-1) 的规律,这也是一种解题思路:数学归纳法。
正确思维应该是,思考青蛙跳的最后一步。
- 青蛙最后跳一步,即 n = (n-1) + 1,则等于青蛙跳 (n-1) 级台阶的跳法。
- 青蛙最后跳两步,即 n = (n-2) + 2,则等于青蛙跳 (n-2) 级台阶的跳法。
- ……
- 青蛙最后跳 (n - 1)步,即 n = 1 + (n-1),则等于青蛙跳 1 级台阶的跳法。
- 青蛙直接跳 n 步上台阶。
最后得出,满足 f(n) = f(n-1) + f(n-2) + … + f(1) + 1 的斐波那契表达式。
题目1390 矩形覆盖
原题链接:http://ac.jobdu.com/problem.php?pid=1390
题目描述:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
算法描述:
不要被”输出“中的 n 为偶数迷惑。就一个一个 n 来。
把长条n*2的覆盖问题分解,思考最后一步加上的一条边:若竖着覆盖一个 2*1 的方块,那么剩下的为 2*(n-1) 块;若横着覆盖,应使用 2 块,覆盖一个 2*2 的块,剩下 2*(n-2),这两种覆盖的方式都各有一种。
最后得出,满足 f(n) = f(n-1) + f(n-2) 的斐波那契表达式。
总结
斐波那契数列的做法,都是需要从最后一步开始思考:最后一步如果这么做,能不能使用(n - subn) 时候的结论?使用时有没有变种,需不需要乘以系数?
通式:f(n) = f(n-1)*coeff(1) + f(n-2)*coeff(2) + … + f(1)*coeff(n-1)
最后需要注意的是避免递归而使用循环。循环时使用数组保存每个结果,而不是一个输入之后再计算。