剑指Offer - 九度1387 - 斐波那契数列

剑指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 }

 

你可能感兴趣的:(FF)