斐波那契數列


簡單的說就是f[n]=f[n-1]+f[n-2],f[1]=1,f[2]=1的一個數列。

1.根據遞推式可以簡單得出一個遞歸求法。

typedef long long ll;

ll f(ll x){
    if(x==1||x==2)return 1;
    else return f(x-1)+f(x-2);
}

int main(){
    ll n;
    scanf("%lld",&n);
    printf("%lld\n",f(n));
}

2.顯然得出這樣得一個遞歸式子出現了大量得重復計算,可以記憶化優化

typedef long long ll;
const int maxn=50;
ll f[maxn];

int main(){
    ll n;
    f[1]=f[2]=1;
    scanf("%lld",&n);
    for(int i=3;i<=n;i++){
        f[i]=f[i-1]+f[i-2];
    }
    printf("%lld\n",f[n]);
}

3.如果可以構造如圖所示的矩陣,那么連續給矩陣乘以n個這樣的矩陣就可以得到fn

 

 又因為矩陣滿足結合律,所以可以用快速冪的方式,除去矩陣乘法的時間復雜度,O(logn)就可以得到斐波那契數列的第n項。

對於常系數線性齊次遞推得到如下結論:

const int N=10,M=10;
long long a[10];
long long f[10];

struct matrix{
    int n,m;
    long long a[N][M];
    matrix(){//    初始化2*2的單位矩陣
        n=m=2;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                a[i][j]=0;
            }
        }
        for(int i=0;i<n;i++){
            a[i][i]=1;
        }
    }
    void clear(){
        //memset(a,0,sizeof(a));
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                a[i][j]=0;
            }
        }
    }
    matrix operator+(const matrix &b)const{
        matrix tmp;
        tmp.clear();
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                tmp.a[i][j]=a[i][j]+b.a[i][j];
            }
        }
        return tmp;
    }
    matrix operator*(const matrix &b)const{
        matrix tmp;
        tmp.clear();
        for(int i=0;i<n;i++){
            for(int j=0;j<b.m;j++){
                for(int k=0;k<m;k++){
                    tmp.a[i][j]=((a[i][k]*b.a[k][j])+tmp.a[i][j]);
                }
            }
        }
        return tmp;
    }
};

matrix pow2(matrix A,int n){
    matrix B;
    while(n>0){
        if(n&1)B=B*A;
        A=A*A;
        n/=2;
    }
    return B;
}

long long solve(long long a[],long long f[],int n,int m){
    matrix A,B;
    A.clear();
    B.clear();
    A.n=B.n=n;
    A.m=n;
    B.m=1;
    for(int i=0;i<n-1;i++){
        A.a[i+1][i]=1;
    }
    for(int i=0;i<n;i++){
        B.a[i][0]=f[n-i-1];
        A.a[0][i]=a[n-i-1];
    }
    A=pow2(A,m);
    B=A*B;
    return B.a[n-1][0];
}

int main(){//求斐波那契數列第m項
    a[0]=1,a[1]=1;      //系數
    f[0]=0,f[1]=1;      //前n項
    int m;
    scanf("%d",&m);
    printf("%lld\n",solve(a,f,2,m));
    return 0;
}

4.模素數下求類斐波那契數得第n項(2019南昌網絡賽 H. The Nth Item)

題意:Q個詢問,每次求F(N),但是N要用上一次詢問的結果得到,結果mod998244353。

由待定系數法構造等比數列,求得F(n)=1/sqrt(17)*[((3+sqrt(17))/2)^n-((3-sqrt(17))/2)^n]。發現式子中有根號,要做得就是找到一個可以代替根號17得數,也就是17的二次剩余。

例如本題(2019南昌網絡賽 H. The Nth Item)。假設二次剩余為x,那么公式里的全部sqrt(17)都可以換為x。F(n)=1/x*[((3+x)/2)^n-((3-x)/2)^n]。

對於一個數x,求(x^n)%p,顯然可以用歐拉定理降冪為x^(n%phi(p)+phi(p)),本題p=998244353,那么指數n最大便為:1996488703。我們可以分塊預處理,設N=sqrt(1996488703),把X[0]=x^0,X[1]=x^1,...,X[n]=x^N預處理出來,再把pre[0]=x^(0*N),pre[1]=x^(1*N),...,pre[N]=x^(N*N))。

求出來,這樣對於一個詢問n=a*N+b,我們其實就是求 (x^(a*N))*(x^b),即pre[a]*X[b]=pre[n/N]*X[n%N]。

using namespace std;
const int N = 5e4;
const ll mod = 998244353;
const ll inv17 = 438914993;//sqrt(17)的二次剩余
const ll x1 = 736044383;//(3+sqrt(17))/2
const ll x2 = 262199973;//(3-sqrt(17))/2
ll X1[N+10],X2[N+10],pre1[N+10],pre2[N+10];
ll ans,n,q,nn,res;
ll mo(ll x){ return x>=mod?x%mod:x; }
void Init(){
    pre1[0]=pre2[0]=X1[0]=X2[0]=1;
    for(int i=1;i<=N;i++)
        X1[i]=mo(X1[i-1]*x1),X2[i]=mo(X2[i-1]*x2);        
    for(int i=1;i<=N;i++)
        pre1[i]=mo(pre1[i-1]*X1[N]),pre2[i]=mo(pre2[i-1]*X2[N]);            
}
int main(){
    Init();
    scanf("%lld%lld",&q,&n);
    res=ans=0;
    while(q--){
        n^=(res*res);
        nn=n%(mod-1)+mod-1; 
        res=mo(pre1[nn/N]*X1[nn%N])-mo(pre2[nn/N]*X2[nn%N]);
        res=mo(res+mod);
        res=mo(res*inv17);
        ans^=res;
        
    }
    printf("%lld\n",ans);
    return 0;    
}

5.斐波那契數列又稱為黃金分割數列

當n趨向於無窮大時,前一項與后一項的比值越來越逼近黃金分割0.618(或者說后一項與前一項的比值小數部分越來越逼近0.618)。

1÷1=1,1÷2=0.5,2÷3=0.666...,3÷5=0.6,5÷8=0.625…………,55÷89=0.617977……………144÷233=0.618025…46368÷75025=0.6180339886…...
證明:
f n+f n+1=f n+2
兩邊除以f n+1得:f n/f n+1+1=f n+2/f n+1
設f無窮大為x,n為無窮大,得:x+1=1/x
解得:x=(√5-1)/2
 

6.斐波那契數與楊輝三角

楊輝三角左對齊,成如圖所示排列,將同一斜行的數加起來,即得一數列1、1、2、3、5、8、……
公式表示如下:
f⑴=C(0,0)=1。
f⑵=C(1,0)=1。
f⑶=C(2,0)+C(1,1)=1+1=2。
f⑷=C(3,0)+C(2,1)=1+2=3。
f⑸=C(4,0)+C(3,1)+C(2,2)=1+3+1=5。
f⑹=C(5,0)+C(4,1)+C(3,2)=1+4+3=8。
f⑺=C(6,0)+C(5,1)+C(4,2)+C(3,3)=1+5+6+1=13。
……
f(n)=C(n-1,0)+C(n-2,1)+…+C(n-1-m,m) (m<=n-1-m)
 

7.其他公式

與集合子集: 斐波那契數列的第n+2項同時也代表了 集合 {1,2,...,n}中所有不 包含 相鄰正 整數 子集 個數。
 

奇數項求和:

 

偶數項求和:  

 

前n項求和:fn+2-1

 

平方求和:     (值得一提的是這個公式也說明了用斐波那契數的前n項為邊長的n個正方形可以構造出一個矩形)

 

隔項關系:

f(2n-2m-2)[f(2n)+f(2n+2)]=f(2m+2)+f(4n-2m) [ n〉m≥-1,且n≥1]
 

兩倍項關系:f(2n)/f(n)=f(n-1)+f(n+1)

 

其他公式:

 

當且僅當,n%4==0時,f[n]%3==0等等。。。。。。

8.尾數循環

 
斐波那契數列的個位數:一個60步的循環
11235,83145,94370,77415,61785,38190,
99875,27965,16730,33695,49325,72910…
進一步,斐波那契數列的最后兩位數是一個300步的循環,最后三位數是一個1500步的循環,最后四位數是一個15000步的循環,最后五位數是一個150000步的循環。
 

9.廣義斐波那契數列

斐波那契—盧卡斯數列
盧卡斯數列1、3、4、7、11、18…,也具有斐波那契數列同樣的性質。(我們可稱之為斐波那契—盧卡斯遞推:從第三項開始,每一項都等於前兩項之和f(n) = f(n-1)+ f(n-2)。
盧卡斯數列的通項公式為 f(n)=[(1+√5)/2]^n+[(1-√5)/2]^n
這兩個數列還有一種特殊的聯系(如下表所示),F(n)*L(n)=F(2n),及L(n)=F(n-1)+F(n+1)
 
斐波那契數列還讓我們聯想到 佩爾數列:1,2,5,12,29,…,也有|2*2-1*5|=|5*5-2*12|=…=1。
佩爾數列Pn的遞推規則:P1=1,P2=2,Pn=P(n-2)+2P(n-1).

據此類推到所有根據前兩項導出第三項的通用規則:f(n) = f(n-1) * p + f(n-2) * q,稱為廣義斐波那契數列。
 
當p=1,q=1時,我們得到斐波那契—盧卡斯數列。
當p=1,q=2時,我們得到佩爾—勾股弦數(跟邊長為整數的 直角三角形有關的數列集合)。
當p=2,q=-1時,我們得到等差數列。其中f1=1,f2=2時,我們得到自然數列1,2,3,4…。自然數列的特征就是每個數的平方與前后兩數之積的差為1(等差數列的這種差值稱為 自然特征)。
具有類似黃金特征、勾股特征、自然特征的廣義——斐波那契數列p=±1。
當f1=1,f2=2,p=2,q=0 時,我們得到等比數列1,2,4,8,16……
 

10.其他

鄧肯多夫定理?(Zeckendorf's Theorem):任何一個正整數一定能分解成若干個不重復且不相鄰的斐波那契數之和。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM