**:矩陣快速冪求斐波那契數列(初學整理)
參考文章:
感謝以上兩位大神讓我明白了如何用矩陣快速冪求斐波那契數列。
題外話:線代真的要好好學,這學期剛好學線代,初期還是蠻認真的,可是後來就勉強能聽懂,然後慢慢~~。萬惡的線代,上學期去湘潭大學參加中南地區程式設計邀請賽第一題就是乙個矩陣,三個人都沒有學過線代,可那題的通過率還是蠻高的,最終只做了一題打鐵的佳績!
感覺學起來還是蠻簡單的,蠻好理解的,以下就我的理解借用大神們一點想法來把矩陣快速冪整理總結!
第一部分:矩陣的基礎知識
1.結合性 (
ab)c=a(bc).
2.對加法的分配性 (
a+b)c=ac+bc
,c(a+b
)=ca+cb .
3.對數乘的結合性
k(ab)=
(ka)b =a(kb).
4.關於轉置
(ab)'=b'a'.
乙個矩陣就是乙個二維陣列,為了方便宣告多個矩陣,我們一般會將矩陣封裝乙個類或定義乙個矩陣的結構體,我採用的是後者。(弱雞的我也直只會用結構體實現)
第二部分:矩陣相乘
若a為n×k矩陣,b為k×m矩陣,則它們的乘積ab(有時記做a·b)將是乙個n×m矩陣。前乙個矩陣的列數應該等於後乙個矩陣的行數,得出的矩陣行數等於前乙個矩陣的行數,列數等於後乙個矩陣的行數。
其乘積矩陣ab的第i行第j列的元素為:
舉例:a、b均為3*3的矩陣:c=a*b,下面的**會涉及到兩種運算順序,第一種就是直接一步到位求,第二種就是每次求一列,比如第一次,c00+=a00*b00,c01+=a00*b01……第二次c00+=a00*b10,c01+=a01*b11……以此類推。。。
c00 = a00*b00 + a01*b10 + a02*b20 c01 = a00*b01 + a01*b11 + a02*b21 c02 = a00*b02 + a01*b12 + a02*b22 c10 = a10*b00 + a11*b10 + a12*b20 c11 = a10*b00 + a11*b11 + a12*b21 c12 = a10*b02 + a11*b12 + a12*b22 c20 = a20*b00 + a21*b10 + a22*b20 c21 = a20*b01 + a21*b11 + a22*b21 c22 = a20*b02 + a21*b12 + a22*b22 c00 = a00*b00 + a01*b10 + a02*b20 c01 = a00*b01 + a01*b11 + a02*b21c02 = a00*b02 + a01*b12 + a02*b22
下面先來實現乙個矩陣相乘的函式吧。
const int mod=10000;
struct mat
; mat mat_mul(mat x,mat y)//實現兩個矩陣相乘,返回的還是乙個矩陣。
return res;
}
學了現代的話這個是很好理解的(個人認為)。
第三部分:矩陣快速冪 //其實和普通快速冪類似,只不過這裡需要得到的是乙個矩陣
神馬是冪?【很多時候會被高大上的名字嚇到。。。導致學習效率降低。。。其實沒辣麼可怕,很簡單!!!】
冪又稱乘方。表示乙個數字乘若干次的形式,如n個a相乘的冪為a^n ,或稱a^n為a的n次冪。a稱為冪的底數,n稱為冪的指數。——引自.度娘百科
這類題,指數都是很大很大很大很大很大很大很大的。。。霸王硬上弓的話,很容易超時的 t_t 。。。所以得快速冪→_→
學過之後發現,其實矩陣快速冪 的核心思想跟 以前學過的快速冪取模非常非常相似,只是矩陣乘法需要另外寫個函式,就是上面那個**。。。
快速冪的思路就是:
設a為矩陣,求a的n次方,n很大,1000000左右吧。。。
先看小一點的,a的9次方
a^9
= a*a*a*a*a*a*a*a*a 【乙個乙個乘,要乘9次】
= a*(a*a)*(a*a)*(a*a)*(a*a)【保持格式的上下統一,所以加上這句】
= a*(a^2)^4 【a平方後,再四次方,還要乘上剩下的乙個a,要乘6次】
= a*((a^2)^2)^2【a平方後,再平方,再平方,還要乘上剩下的乙個a,要乘4次】
也算是一種二分思想的應用吧,1000000次冪,暴力要乘1000000次,快速冪就只要(log2底1000000的對數) 次,大約20次。。。這。。。我沒錯吧。。。
單位矩陣: n*n的矩陣 mat ( i , i )=1; 任何乙個矩陣乘以單位矩陣就是它本身 n*單位矩陣=n, 可以把單位矩陣等價為整數1。(單位矩陣用在矩陣快速冪中)
例如下圖就是乙個7*7的單位矩陣:
下面來實現乙個矩陣快速冪:
int pow(int n)//還是小範圍資料來說吧,要不然返回值的型別自己定義
return res.a[0][1];
}//時間複雜度log(n)
但是矩陣如何與斐波那契聯絡在一起呢???
找了很多部落格,看了第二位大神的部落格才理解。
對於矩陣乘法與遞推式之間的關係:
如:在斐波那契數列之中
f[i] = 1*f[i-1]+1*f[i-2] f[i-1] = 1*f[i-1] + 0*f[i-2];
即
就這兩幅圖完美詮釋了斐波那契數列如何用矩陣來實現。
下面一poj3070/nyoj148為例
給出了矩陣相乘的定義,要你求出斐波那契的第n項對1e4取餘。
**一:在網上看到的很簡潔的**
#include #include #include #include using namespace std;
typedef long long ll;
const int mod=10000;
typedef vectorvec;
typedef vectormat;
mat mul(mat &a,mat &b)//表示不會這樣用,,,,}}
return c;
}mat pow(mat a,ll n)
;mat mat_mul(mat x,mat y)
void mat_pow(int n)
printf("%i64d\n",res.a[0][1]);
}int main()
return 0;
}
快速冪(矩陣快速冪)
求 3 0 3 1 3 n mod 1000000007 input 輸入乙個數n 0 n 10 9 output 輸出 計算結果 sample input 3sample output 40 分析 利用等比數列的求和公式得所求和是 3 n 1 1 2,如果暴力求3 n 1 會超時,這裡引入快速冪來...
快速冪 矩陣快速冪
快速冪 正常情況下求乙個數的冪時間複雜度為o n 而快速冪能把時間複雜度降到o logn 舉個例子 求5的13次方 思想首先把13化為二進位制 1101,即13 1101 8 1 4 1 2 0 1 1 即5 13 58 1 54 1 52 0 5 1 15 5 8 1 5 4 1 5 2 0 5 ...
快速冪 矩陣快速冪
快速冪 我們求a ba b ab最直接的方法就是把a乘b次這樣的話複雜度就是o n o n o n 但是在比賽時面對1e9的資料時還是會輕鬆超時的,此時就需要一種更快的乘法來幫助我們 我們把b拆成二進位制的形式得到a ba b ab a 10.01 a a1 0.01此時對b分解得到的序列10.01...