矩陣冪可以用來解決斐波那契問題,圖的路徑條數問題。
在計算矩陣冪的過程中,如果用樸素的列與行枚舉求和:
例如——
複雜度是O(N)。
所以引進了矩陣快速冪來計算。
首先來看快速冪——
快速冪就是把指數再化成 底數加指數 的形式,例如:
如何拆分呢?
ll quick(ll a,ll b ,ll c){
ll ans=1;
while(b){
if(b&1){
ans=(ans*a)%c;
}
b>>=1;
a=(a*a)%c;
}
return ans;
}
因爲是指數再求指數所以時間複雜度爲 O(log₂N)。
把它應用到矩陣運算中也是一樣,把矩陣看成一個數。
放兩個模板:
int n,m,T;
struct Node{
int contain[MAXX][MAXX];
Node(){
for(int i=0;i<MAXX;i++){
for(int j=0;j<MAXX;j++){
contain[i][j]=0;
}
}
}
};
矩陣乘法:
Node multi(int a[][MAXX],int b[][MAXX]){ //兩矩陣乘
Node ans;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
for(int k=0;k<n;k++){
ans.contain[i][j]+=a[i][k]*b[k][j];
}
//ans.contain[i][j]%=10000;
}
}
return ans;
}
矩陣的快速冪:Node Pow(Node ex,int k){//矩陣K次冪
Node res;
for(int i=0;i<n;i++){ //單位矩陣
res.contain[i][i]=1;
}
while(k){
if(k&1){
res=multi(res.contain,ex.contain);
}
ex=multi(ex.contain,ex.contain);
k>>=1;
}
return res;
}
用來解決斐波那契問題 即 把遞推式轉化成矩陣乘法的形式:當然,沒有公式的時候還是先要靠數學推出來的orz。
哦還有,多次冪得到的數很大超範圍,一般都要取模。
一開始我很糾結取模的問題,爲啥老模10000007。
它就是怕你範圍太大,用個大素數把結果分散一點,有點哈希的意思。
不會影響結果的,總之,它要你怎麼模就怎麼模嘍= =。