【编辑】斐波那契数列

来源:互联网 发布:简单新闻发布系统源码 编辑:程序博客网 时间:2024/06/07 00:45

  菲波那契数列(Fibonacci sequence)指的是这样一个数列:

        1,1,2,3,5,8,13,21,34,55,……

这个数列从第三项开始,每一项都等于前两项之和。可将其递归定义为:

        F(1) = 1
        F(2) = 1
        F(n) = F(n - 1) + F(n - 2)     n > 2

因此,可用递归的办法编写程序计算该数列第 N 项的值:

        // header inherited from ISO C
        #include <cassert>               // for assert
        // boost header
        #include <boost/bigint.hpp>      // for bigint

        boost::bigint fibonacci(const boost::bigint &n)
        {
            assert(n != 0);

            if ( n == 1 || n == 2 ) return 1;

            return fibonacci(n - 1) + fibonacci(n - 2);
        }

不过,递归效率实在是太差了,不信你可以试试计算第 50 项的值,看看需要多久。使用迭代可以大大提高运行效率:

        boost::bigint fibonacci(const boost::bigint &n)
        {
            assert(n != 0);

            if ( n == 1 || n == 2 ) return 1;

            boost::bigint tmp, f1 = 1, f2 = 1;
            for ( boost::bigint i = 2; i != n; ++i )
            {
                tmp = f1 + f2;
                f1.swap(f2);
                f2.swap(tmp);
            }
   
            return f2;
        }

这回计算第 50 项的值一下子就出来了。

    此外,也可以使用公式来计算第 N 项的值:

        

Boost 库目前似乎还没有针对 bigint 进行开方及求 N 次方的函数(若有请告知),故此,鄙人也就暂不将该公式代码化啦。

    下面这个函数的功能是构建一个 n 项的菲波那契数列

        // ISO C++ header
        #include <vector>
        // header inherited from ISO C
        #include <cassert>               // for assert
        // boost header
        #include <boost/bigint.hpp>      // for bigint

        void form_fib_seq(std::vector<boost::bigint>::size_type n, // 菲波那契数列的项数
                          std::vector<boost::bigint> &vFibSeq)     // 用于保存菲波那契数列
        {
            assert(n != 0);  // 项数不能为 0
   
            if ( n > 2 ) // 如果需要构建的数列的项数大于 2
            {
                // 先将第一、二项的值保存到容器里
                vFibSeq.push_back(1);
                vFibSeq.push_back(1);
                for ( std::vector<boost::bigint>::size_type i = 2;
                      i != n; ++i )
                {
                    // 从第三项开始,每一项都等于前两项之和
                    vFibSeq.push_back(vFibSeq[i - 1] + vFibSeq[i - 2]);
                }
            }
            else  // 如果需要构建的数列的项数小于/等于 2
            {
                while ( n-- != 0 )
                {
                    vFibSeq.push_back(1);
                }
            }
        }


    斐波那契序列有着广泛的应用。    1)例如有一种两个游戏,名叫“尼姆”。游戏方法是由两个人轮流取一堆粒数不限的砂子。先取的一方可以取任意粒,但不能把这堆砂子全部取走。后取的一方,取数也多少不拘,但最多不能超过对方所取砂子数的一倍。然后又轮到先取的一方来取,但也不能超过对方最后一次所取砂子的一倍。这样交替地进行下去,直到全部砂子被取光为止,谁能拿到最后一粒砂子,谁就算胜利者。    在这个游戏中,若所有砂子的粒数是个斐波那契数的话,那么后取的一方稳操胜券,而所有的砂子不是一个斐波那契数的话,那么先取的一方稳胜。
    2) 一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法。
   3 ) 兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔都不死,那么一年以后可以繁殖多少对兔子?

斐波那契数列的整除性与素数生成性

  每3个数有且只有一个被2整除,
  每4个数有且只有一个被3整除,
  每5个数有且只有一个被5整除,
  每6个数有且只有一个被8整除,
  每7个数有且只有一个被13整除,
  每8个数有且只有一个被21整除,
  每9个数有且只有一个被34整除,
  ....... 

斐波那契数与植物花瓣

  3………………………百合和蝴蝶花
  5………………………蓝花耧斗菜、金凤花、飞燕草、毛茛花
  8………………………翠雀花
  13………………………金盏
  

和玫瑰
  21………………………紫宛
  34、55、89……………雏菊