矩陣快速冪


一、前期鋪墊

 在講矩陣快速冪之前,我們先來看一下整數快速冪。求 X 的 N 次方。

 舉個例子,在求 x^19時,我們可以拆分成 x^16、x^2 和 x的乘積。我們觀察19的二進制數(10011),發現二進制第 i 位上的值為 1 ,在乘積中就要有 x 的 2^i 的一項。據此我們可以利用遍歷二進制數的每一位快速求出 X^N。

 代碼如下:

  

 1 ll QuickPow(ll x,ll n)
 2 {
 3     ll tmp = (ll)x;
 4     ll res = 1;
 5     for(ll i=0;(1<<i)<=n;i++)
 6     {
 7         if(n&(1<<i))
 8         {
 9             res=(res*tmp)%mod;
10         }
11         tmp=(tmp*tmp)%mod;
12     }
13     return res;
14 }

也可以寫成下面這樣:

 1 ll QuickPow(ll x,ll n)
 2 {
 3     ll tmp = x;
 4     ll res=1;
 5     while(n)
 6     {
 7         if(n&1)
 8             res=(res*tmp)%mod;
 9         tmp = (tmp*tmp)%mod;
10         n>>=1;
11     }
12     return res;
13 }

二、矩陣快速冪的實現過程

  現在問題變成求解矩陣 A 的 N 次方,我們可以類比整數快速冪,寫一個矩陣的結構體,用一個matmul函數來定義矩陣的乘法,具體實現過程與整數快速冪類似。

struct mat
{
    ll m[maxn][maxn];
}unit;
void init()
{
    for(int i=1;i<maxn;i++)
        unit.m[i][i]=1;
}
mat matmul(mat a,mat b)
{
    mat ans;
    ll tmp =0;
    for(int i=1;i<maxn;i++)
    {
        for(int j=1;j<maxn;j++)
        {
            tmp=0;
            for(int k=1;k<maxn;k++)
            {
                tmp=(tmp+a.m[i][k]*b.m[k][j])%mod;
            }
            ans.m[i][j]=tmp;
        }
    }
    return ans;
}
mat QuickPow(mat a,ll n)
{
    mat tmp = a;
    mat res=unit;
    while(n)
    {
        if(n&1)
            res=matmul(res,tmp);
        tmp = matmul(tmp,tmp);
        n>>=1;
    }
    return res;
}

三、應用

第一步先要列出遞推式:

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

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

,

簡寫成T * A(n-1)=A(n),T矩陣就是轉移矩陣,而且一定是一個常數矩陣,

由此得到A(n)= A(1) * T^(n-1)

T^(n-1)可以利用矩陣快速冪計算出來,而A(1)可以手動計算,就可以得到A(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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM