中级篇——斐波那契数列详解

本文介绍斐波那契数列的多种高效计算方法,包括矩阵快速幂算法求解特定项及其平方和,以及如何求解斐波那契数列的前n位和后n位数字。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

斐波那契主要分为以下题型:

1.求具体某项的值(一般在45项以内,打表即可)

2.求具体某一项模K(通常是个大数项,一般采用矩阵法)

3.求斐波那契前几位数字(例如:HDU 的 3117 题)

4.求解 Fibonacci 的后多少位,这个和取模类似

5.求前n项和(矩阵法)

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

        需要用到线性代数矩阵相乘的方法

例1:HIT  2060

As we know , the Fibonacci numbers are defined as follows:

""""

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
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(1)

    1  , 1  , 0                x          F(1)       =     F(2)

    0  , 1  , 1 }                         s(1)  }           s(2)  }  

#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;
    }
}

例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.   


Sample Input 2 1 1  
                           3 2 3     
Sample Output

                              196 

{ 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;
}

求前n位或后n位类型题

后n位即对10^n取余后printf("%0nd\n");前n位的求法略难,领会不了就记模板吧~

例:HDU 3117

The Fibonacci sequence is the sequence of numbers such that every element is equal to the sum of the two previous elements, except for the first two elements f0 and f1 which are respectively zero and one.

What is the numerical value of the nth Fibonacci number?
 

Input
For each test case, a line will contain an integer i between 0 and 108 inclusively, for which you must compute the ith Fibonacci number fi. Fibonacci numbers get large pretty quickly, so whenever the answer has more than 8 digits, output only the first and last 4 digits of the answer, separating the two parts with an ellipsis (“...”).

There is no special way to denote the end of the of the input, simply stop when the standard input terminates (after the EOF).
 

Sample Input
0 1 2 3 4 5 35 36 37 38 39 40 64 65
 

Sample Output
0 1 1 2 3 5 9227465 14930352 24157817 39088169 63245986 1023...4155 1061...7723 1716...7565

思路~:斐波那契数列前50项左右<10^8打表输出即可,大于10^8的用矩阵法计算值,后四位——对10000取余即可(注意%04d输出四位),

前四位求法:

  123456.32=1234.56*10^2  
s=d.xxx*10^(len-4)

log10(s)=log10(d.xxxxx)+log10(10^(len-4))=log10(d.xxxx)+len-4;

log10(s)+4-len=log10(d.xxxx)

d.xxxx=10^(log10(s)+4-len)

s=(1/sqrt(5))*[(1+sqrt(5))/2.0]^n;

len=(int)log10(s)+1;

d.xxxx=10^(log10(s)+4-((int)log10(s)+1))=10^(log10(s)-(int)log10(s)+3);                              //看不懂,直接上代码

#include <iostream>
#include <stdio.h>
#include <math.h>
#define Mod 10000
using namespace std;
long long f[100];
const int MAX = 2;
typedef  struct
{
    long long  m[MAX][MAX];
}  Matrix;
Matrix P = {0,1,
            1,1};
Matrix I = {1,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()
{
    double log_s=0.0;
    Matrix tmp;
    int n,bit=0;
    f[0]=0;f[1]=1;
    for(int i=2;i<=50;i++)
    {
        f[i]=f[i-1]+f[i-2];
        if (f[i]>=100000000)
        { bit=i-1;break;}
    }
    while(cin>>n)
    {
        if (n<=bit) cout<<f[n]<<endl;
        if (n>bit)
        {
            tmp=quickpow(n);
            int ans_e=tmp.m[0][1];
            log_s=log10(1.0/sqrt(5)) +(double)n*log10((1.0+sqrt (5))/2.0);
            int ans_s=(int)(pow(10,log_s-(int)log_s+3));
            cout<<ans_s<<"...";
            printf("%04d\n",ans_e);
        }
    }
    return 0;
}


简单斐波那契问题到此为止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值