1. 程式人生 > >矩陣快速冪模版

矩陣快速冪模版

const int N=10;  
int tmp[N][N];  
void multi(int a[][N],int b[][N],int n)  
{  
    memset(tmp,0,sizeof tmp);  
    for(int i=0;i<n;i++)  
        for(int j=0;j<n;j++)  
        for(int k=0;k<n;k++)  
        tmp[i][j]+=a[i][k]*b[k][j];  
    for(int i=0;i<n;i++)  
        for(int j=0;j<n;j++)  
        a[i][j]=tmp[i][j];  
}  
int res[N][N];  
void Pow(int a[][N],int n)  
{  
    memset(res,0,sizeof res);//n是冪,N是矩陣大小  
    for(int i=0;i<N;i++) res[i][i]=1;  
    while(n)  
    {  
        if(n&1)  
            multi(res,a,N);//res=res*a;複製直接在multi裡面實現了;  
        multi(a,a,N);//a=a*a  
        n>>=1;  
    }  
}  

上訴res陣列就等同於普通快速冪初始化的1,原理想通的,這個矩陣叫單位矩陣E,性質就是E*A=A,就是1*a=a,一樣,單位矩陣就是對角線全是1其他全是0;

最終算出的結果是一個res矩陣,具體有什麼用就看下面的應用。

應用篇

主要通過把數放到矩陣的不同位置,然後把普通遞推式變成"矩陣的等比數列",最後快速冪求解遞推式:

先通過入門的題目來講應用矩陣快速冪的套路(會這題的也可以看一下套路):

例一:http://poj.org/problem?id=3070
題目:斐波那契數列f(n),給一個n,求f(n)%10000,n<=1e9;

(這題是可以用fibo的迴圈節去做的,不過這裡不講,反正是水題)

矩陣快速冪是用來求解遞推式的,所以第一步先要列出遞推式:

 f(n)=f(n-1)+f(n-2)

第二步是建立矩陣遞推式,找到轉移矩陣:

,簡寫成T * A(n-1)=A(n),T矩陣就是那個2*2的常數矩陣,而

這裡就是個矩陣乘法等式左邊:1*f(n-1)+1*f(n-2)=f(n);1*f(n-1)+0*f(n-2)=f(n-1);

這裡還是說一下構建矩陣遞推的大致套路,一般An與A(n-1)都是按照原始遞推式來構建的,當然可以先猜一個An,主要是利用矩陣乘法湊出矩陣T,第一行一般就是遞推式,後面的行就是不需要的項就讓與其的相乘係數為0。矩陣T就叫做轉移矩陣(一定要是常數矩陣),它能把A(n-1)轉移到A(n);然後這就是個等比數列,直接寫出通項:此處A1叫初始矩陣。所以用一下矩陣快速冪然後乘上初始矩陣就能得到An,這裡An就兩個元素(兩個位置),根據自己設定的A(n)對應位置就是對應的值,按照上面矩陣快速冪寫法,res[1][1]=f(n)就是我們要求的。

給一些簡單的遞推式
1.f(n)=a*f(n-1)+b*f(n-2)+c;(a,b,c是常數)


2.f(n)=c^n-f(n-1) ;(c是常數)


https://blog.csdn.net/wust_zzwh/article/details/52058209