剑指Offer - 九度1387 - 斐波那契数列
2013-11-24 03:08
题目描述:

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。斐波那契数列的定义如下:

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入包括一个整数n(1<=n<=70)。

输出:

对应每个测试案例,

输出第n项斐波那契数列的值。

样例输入:
3
样例输出:
2
题意分析:
  斐波那契数列的定义:
    f[1] = 1, f[2] = 1
    f[n] = f[n - 1] + f[n - 2], n >= 3
  数学推导上,可以用特征根方程求出x^2 = x + 1的俩根 x = (1 土 sqrt(5)) / 2,编程的话你当然不会这么无聊去惹出一对无理数来。
  方法一,从f[1]、f[2]开始逐个计算f[3]到f[n],求出f[n]。时间复杂度O(n),空间复杂度O(1)。
  方法二,用矩阵来计算。
    将[f[n + 1], f[n]]作为一个列向量v[n],从v[n - 1] = [f[n - 1], f[n - 2]]到v[n]要经过一次线性变换T(v),T对应的矩阵A就是我们要构造的(当然是对应于自然基的)。
    设A = [a, b; c, d], v[n] = A * v[n - 1],显然(a, b, c, d)的解不唯一,就构造个最简单的就行了:[a, b, c, d] = [1, 1, 1, 0]。
    v[n] = A^(n - 1) * v[1],于是问题就转化成了矩阵的快速幂。时间复杂度O(log(n)),递归求解空间复杂度O(log(n))。
  数据范围小的话,用方法一就行,一般int和long long数据范围也只能支持几十个Fibonacci数。要计算大数的话,高精度算法配合方法二的O(log(n))效率肯定是免不了的。
下面是O(n)简单算法,数据量才70就不大材小用了,Over engineered是个坏习惯。
 1 // 651776    zhuli19901106    1387    Accepted    点击此处查看所有case的执行结果    1020KB    456B    0MS
 2 // 201311151646
 3 #include   <cstdio>
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     int n, i;
 9     long long int f1, f2, f3;
10     
11     while(scanf("%d", &n) == 1){
12         if(n == 0){
13             printf("0\n");
14             continue;
15         }
16         if(n == 1){
17             printf("1\n");
18             continue;
19         }
20         f1 = 0;
21         f2 = 1;
22         for(i = 1; i < n; ++i){
23             f3 = f1 + f2;
24             f1 = f2;
25             f2 = f3;
26         }
27         
28         printf("%lld\n", f3);
29     }
30     
31     return 0;
32 }

 

 posted on 2013-11-24 03:41  zhuli19901106  阅读(274)  评论(0编辑  收藏  举报