斐波那契數列及其對數時間算法

斐波那契數列及其對數時間算法

前些天做IEEE校內算法賽的時候,遇到了一道關於斐波那契數列的題,要求是對數時間;今天在牛課網上刷leetcode,看到爬樓梯問題,於是在網上搜索了一下,自己參考並總結了下斐波那契數列及其算法。主要參考了知乎這個問題下的回答最高贊回答
斐波那契數列大家應該都很熟悉:0 1 1 2 3 5 8… ,遞推公式如下:
f(n)={f(n1)+f(n2)if2n;f(0)=0,f(1)=1else.

斐波那契數列的同向可以使用特徵根法或者矩陣的乘積來解決:
f(n)=15((1+52)n(152)n).
下面介紹利用矩陣快速冪的對數時間的斐波那契數列算法:
首先從遞推公式我們很容易得到:
[f(n+1)f(n)]=[1110][f(n)f(n1)]=[1110]n[f(1)f(0)].
不妨設A=[1110] ,那麼我們的目標就是求矩陣A的n次冪
在介紹矩陣的快速冪算法之前,我們先介紹一下數的快速冪算法,數的快速冪算法一般有遞歸和位運算兩種:

//遞歸版本
int my_power(int x, int n) {
    //n >= 0
    if(n == 0) return 1;
    return n % 2 ? x * my_power(x, n / 2) : my_power(x, n / 2);
}
//位運算版本
int my_power(int x, int n) {
    //n >= 0
    int result = 1;
    while(n) {
        if(n & 1) result *= x;
        x *= x;
        n >>= 1;
    }
    return result;
}

例如求210 ,10=(1010)(2) ,分二進制位上爲1和爲0兩種情況討論。
所以可以用同樣的方法求矩陣的冪,我們聲明瞭一個二階矩陣類,只給了矩陣的四個元素、默認構造函數和重載operator*:

//Definition for 2-dimension matrix
struct Matrix {
    /*[m00, m01]
      [m10, m11]*/
    int m00, m01, m10, m11;
    Matrix(int a = 0, int b = 0, int c = 0, int d = 0) :
        m00(a), m01(b), m10(c), m11(d) { }
    Matrix& operator*(const Matrix& rhs) {
        //若要對大數取餘,可以對下面的a,b,c,d取餘運算。
        int a = this->m00 * rhs.m00 + this->m01 * rhs.m10; //% mod
        int b = this->m00 * rhs.m01 + this->m01 * rhs.m11; //% mod
        int c = this->m10 * rhs.m00 + this->m11 * rhs.m10; //% mod
        int d = this->m10 * rhs.m01 + this->m11 * rhs.m11; //% mod
        this->m00 = a; this->m01 = b;
        this->m10 = c; this->m11 = d;
        return *this;
    }
};
/*對數算法,利用矩陣的快速冪*/
Matrix fast_multi(int n) {
    Matrix m(1, 1, 1, 0), result(1, 0, 0, 1);
    while(n) {
        if(n & 1) result = result * m;
         m = m * m;
         n >>= 1;
    }
    return result;
}

因此斐波那契數列的第n項的算法爲:

//這裏沒有考慮int溢出
int Fibonacci(int n) {
    Matrix m = fast_multi(n);
    return m.m10;
}

若斐波那契數列的初值爲f0和f1:

//這裏沒有考慮int溢出
int Fibonacci(int n, int f0, int f1) {
    Matrix m = fast_multi(n);
    return (m.m10 * f1 + m.m11 * f0);
}

最開始說到IEEE校內算法賽的那道題是要求斐波那契數列的前n項和
Sn=f(n+2)f(1)
這個結論用數學歸納法是非常容易證明的。

總結:斐波那契數列在數學中非常重要,它的很多性質我也不懂,只是遇到問題就查資料解決,比如這個對數時間的斐波那契第n項的算法,以後如果遇到其他問題再來補吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章