斐波那契数列

前言

说实话写本文的时候Chuck心里是很虚的,因为数学是Chuck内心永远的伤。因为当初玩过ACM所以学了些数学相关的算法,斐波那契算法就是其中之一,然而现在这部分已经忘得差不多了。数学功底还不错的可以多看看,实在看不懂的话应该也不会有太大影响,在实际面试中尚未碰到有面试官问斐波那契数列的题。

正文

斐波那契数列都不陌生,该类型的题目在面试中被问到的几率不是很高,但其实现相对简单,在一些对数学有一定要求的企业可能会考到。其大致主要分为以下题型:
1.求具体某项的值(一般在45项以内,打表即可)
2.求具体某一项模K(通常是个大数项,一般采用矩阵法)
3.求斐波那契前几位数字(例如:HDU 的 3117 题)
4.求解 Fibonacci 的后多少位,这个和取模类似
5.求前n项和(矩阵法)

最常用最好用的——矩阵法

矩阵法涉及矩阵运算的实现,对于代码准确性有较高要求,且基于矩阵的斐波那契公式推导可以考验编程者的数学思维。

斐波那契数列

当所求项数很小的时候,一般采用打表法即逐项计算即可,但斐波那契数列增长迅速,对于一般的数列而言,到第50项时数字就已经非常之巨大,因此需要一种更高效的算法来求解。
以HIT OJ 2060为例

As we know , the Fibonacci numbers.Given two numbers a and b , calculate

Input
The input contains several test cases. Each test case consists of two non-negative integer numbers a and b (0 ≤ a ≤ b ≤1,000,000,000). Input is terminated by a = b = 0.
Output
For each test case, output S mod 1,000,000,000, since S may be quite large.
Sample Input
1 1
3 5
10 1000
0 0
Sample Output
1
16
496035733
题意:给定整数a,b求斐波那契数列第a项到第b项的和,对1,000,000,000取模

进行一波推导
s(n)=s(n-1)+F(n-1)+F(n-2)
{   0  , 1  , 0         {  F(0)           { F(1)
    1  , 1  , 0     x      F(1)       =     F(2)
    0  , 1  , 1 }          s(1)  }          s(2)  }   
以此类推
{   0  , 1  , 0     ^n-1           {  F(0)          {  F(n - 1)
    1  , 1  , 0                x      F(1)       =     F( n )
    0  , 1  , 1 }                     s(1)  }          s( n )  }  

不信可以自己推推看。
代码实现:

#include <iostream>
#define mod 1000000000
#define max 3
using namespace std;
typedef struct                 //建立3x3的矩阵
{
    long long m[max][max];
}matrix;
matrix p={0,1,0,       //按之前推导的定义矩阵p
          1,1,0,
          0,1,1};
matrix q={1,0,0,       //矩阵q为单位阵
          0,1,0,
          0,0,1};
matrix juzhenchengfa(matrix a,matrix b)        //矩阵乘法
{
    int i,j,k;
    matrix c;
    for(i=0;i<max;i++)
    {
        for(j=0;j<max;j++)
        {
            c.m[i][j]=0;
            for(k=0;k<max;k++)
            {
                c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
            }
            c.m[i][j]=(c.m[i][j]%mod+mod)%mod;
        }
    }
    return c;
}
//矩阵幂运算,数学不好的我选择背模版
matrix quickpow(long long n)
{
    matrix a=p,b=q;
    while(n>=1)
    {
        if(n&1) b=juzhenchengfa(a,b);
        n>>=1;
        a=juzhenchengfa(a,a);
    }
    return b;
}
int main()
{
    long long s,e,sum,sum1;
    matrix tmp,tmp1;
    while(cin>>s>>e)
    {
        if(s==0&&e==0) break;
        tmp=quickpow(e);
        sum=(tmp.m[2][0]+tmp.m[2][1]+2*tmp.m[2][2])%mod;
        tmp1=quickpow(s-1);
        sum1=(tmp1.m[2][0]+tmp1.m[2][1]+2*tmp1.m[2][2])%mod;
        cout<<(sum-sum1)%mod<<endl;
    }
}

其实斐波那契数列代码实现最难理解的就是quickpow()函数,对于奇数和偶数的处理略有不同,但代码量并不大,可以考虑背模版记忆。

例2:As we all known , the Fibonacci series : F(0) = 1, F(1) = 1, F(N) = F(N - 1) + F(N - 2) (N >= 2).Now we define another kind of Fibonacci : f(0) = 1 , f(1) = 1 , f(N) = X * f(N - 1) + Y * f(N - 2) (N >= 2).And we want to Calculate S(N) , S(N) = f(0)2 +f(1)2+……+f(n)2.
Input :There are several test cases. Each test case will contain three integers , N, X , Y, N(2<= N <= 2^31 – 1 X : 2<= X <= 2^31– 1 Y : 2<= Y <= 2^31 – 1 )
Output :For each test case , output the answer of S(n).If the answer is too big , divide it by 10007 and give me the reminder.
其实就是斐波那契公式发生了点变化,这种情况下只需要对原有矩阵进行修改即可:

 { 1 ,  1 ,   0 ,   0,           { s(n-1)             { s(n)           {            s(n-1)+f^2(n-1)
   0 , x^2 , y^2 , 2*x*y,          f^2(n-1)             f^2(n)           x^2*f^2(n-1)+2*x*y*f(n-1)*f(n-2)+y^2*f^2(n-2)
   0 ,  1 ,   0,    0,       x     f^2(n-2)       =     f^2(n-1)    =                   f^2(n-1)
   0 , x^2 ,  0 ,   y    }       f(n-1)*f(n-2)  }     f(n)*f(n-1)}               x^2*f(n-1)+y*f(n-1)*f(n-2)        }
#include <iostream>
#include <stdio.h>
#include <cstring>
#define Mod 10007
using namespace std;
const int MAX = 4;
typedef  struct
{
    int  m[MAX][MAX];
}  Matrix;
Matrix P={1,1,0,0,
          0,0,0,0,
          0,1,0,0,
          0,0,0,0};
Matrix I={1,0,0,0,
          0,1,0,0,
          0,0,1,0,
          0,0,0,1};
Matrix matrixmul(Matrix a,Matrix b) //矩阵乘法
{
    int i,j,k;
    Matrix c;
    for (i = 0 ; i < MAX; i++)
        for (j = 0; j < MAX;j++)
        {
            c.m[i][j] = 0;
            for (k = 0; k < MAX; k++)
            c.m[i][j] += (a.m[i][k]* b.m[k][j])%Mod;
            c.m[i][j] %= Mod;
        }
    return c;
}
Matrix quickpow(long long n)
{
    Matrix m = P, b = I;
    while (n >= 1)
    {
        if (n & 1)
        b = matrixmul(b,m);
        n = n >> 1;
        m = matrixmul(m,m);
    }
    return b;
}
int main()
{     int n,x,y,sum;
      Matrix b;
      while(cin>>n>>x>>y)
      {
          sum=0;
          x=x%Mod;
          y=y%Mod;
          P.m[1][1]=(x*x)%Mod;
          P.m[1][2]=(y*y)%Mod;
          P.m[1][3]=(2*x*y)%Mod;
          P.m[3][1]=x;
          P.m[3][3]=y;
          b=quickpow(n);
          for(int i=0;i<4;i++)
            sum+=b.m[0][i]%Mod;
          cout<<sum%Mod<<endl;
      }
return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容