回歸--快速冪與斐波那契數列

在假期里重新回歸算法的學習,首先在這里簡要寫一下利用快速冪來求得斐波那契序列的原理。
具體的代碼和解釋百度里都有涉及,在這里只寫一下自己的推論過程。
由于使用遞歸算法會浪費太多的時間與空間,所以在這里使用矩陣的方法來實現計算。
學過代數的人可以看出,下面這個式子是成立的:


而這個式子可以不斷遞歸,得到下面的式子:

由于Fib[0]與Fib[1]是已知,那么只需求矩陣的次冪就可以了。
在這里使用到的就是快速冪,關于快速冪的解釋看這里:
http://baike.baidu.com/link?url=dbyx1Lo9P_Ca2cRdKuttAobLhFrmlyfGuCYn1MnzHvOVu-QwilkS3guqyxSZNXIWxlW8s9IIPAgf2_swv093Hq
簡單來說就是 使用位運算來快速求得一個數的 多少個次冪。
簡單的位運算有&,|,<<,>>,~,^等,具體使用方法不再贅述。
在這里使用的是快速冪的非遞歸算法。
當求一個數a的n次冪的時候,需要將該數a相乘n次,那么時間復雜度為n,為了減小該時間復雜度,需要減小n。
已知任意一個數k都可以寫成2n0+2n1+2^n2……形式,那么有:
假設n=11,那么:

我們想要求a的11次冪,只需將11的2進制數從低位開始取,每次取一位,將該位數乘2的相應位數(從一開始取位累加)次冪,將a取該數的次冪再累乘即可。
在這里截取網上的相關代碼:

int Qpow(int a,int n)
{
    int ans = 1;
    while(n)
    {
        if(n&1) ans *= a;
        a *= a;
        n >>= 1;
    }
    return ans;
}

而斐波那契數列的求取需要求的是一個矩陣的冪,故需要將函數中的所有乘法替換為22矩陣的乘法,然后將a與ans均替換為22的矩陣,矩陣相乘的函數可根據代數知識獲得:

matrix multi(matrix a, matrix b)//matrix是2*2的矩陣類
{
    matrix tmp;
    for(int i = 0; i < 2; ++i)
    {
        for(int j = 0; j < 2; ++j)
        {
            tmp.m[i][j] = 0;
            for(int k = 0; k < 2; ++k)
                tmp.m[i][j] = (tmp.m[i][j] + a.m[i][k] * b.m[k][j]) ;
        }
    }
    return tmp;
}

替換后的快速冪函數表示為:

int fast_mod(int n)  //a與ans都是2*2的矩陣類型:matrix
{
    a.m[0][0] =a.m[0][1] = a.m[1][0] = 1;
    a.m[1][1] = 0;      //初始矩陣的值
    ans.m[0][0] = ans.m[1][1] = 1;  // ans 初始化為單位矩陣 
    ans.m[0][1] = ans.m[1][0] = 0;
    while(n)
    {
        if(n & 1)  
        ans = multi(ans, a);
        a = multi(a, a);
        n >>= 1;
    }
    return ans.m[0][1];
}

如果需要求某個斐波那契數取數b的模,那么根據代數知識,矩陣的每個數都需要求得該數的模,且每次相乘都需取模,則在矩陣相乘的函數中每次相乘后取一次模即可。
位置代碼如下:

for(int k = 0; k < 2; ++k)
tmp.m[i][j] = (tmp.m[i][j] + a.m[i][k] * b.m[k][j]) % b;//b是要取的模
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容