快速冪與矩陣快速冪

冪運算

冪運算\(a^b\)\(b\)\(a\)相乘的結果.
C++自帶的冪函數pow是最樸素的\(O(b)\)算法,效率很是低,因此若是要用到大量冪運算,最好本身打一個快速冪.算法

快速冪

\(a^b\%p\)的值.數組

  1. \(b=1\)時,返回\(a%p\).
  2. \(2\mid b\)時,返回\(pow(a,\frac{b}{2},p)^2%p\).
  3. \(2\nmid b\)時,返回\(pow(a,\frac{b}{2},p)^2%p*a%p\).
    時間複雜度爲\(O(\log{b})\).
long long poww(long long a,long long b,long long p) {
    if(b==1) return a%p;
    long long t=1;
    t=poww(a,b/2,p);
    t=t*t%p;
    if(b%2) t=t*a%p;
    return t;
}

矩陣乘法

運算方法

矩陣加法,減法,矩陣乘常數這三種運算都很簡單,這裏不贅述.
有兩個分別爲\(n\times m\),\(m\times p\)的矩陣\(a,b\)相乘,結果是一個\(n\times p\)的矩陣\(c\).
\(c[i][j]=\sum\limits_{k=1}^{m}{a[i][k]*b[k][j]}\).
矩陣乘法.gif
代碼用結構體實現.函數

struct mat {
    long long (*x)[505]=new long long[505][505];//若是矩陣比較小就直接開數組,太大就用指針.
    friend mat operator * (mat a,mat b) {//重載
        mat c;
        for(long long i=1; i<=n; i++) {
            for(long long j=1; j<=m; j++) {
                for(long long k=1; k<=p; k++) {
                    c.x[i][j]=(c.x[i][j]+(a.x[i][k]*b.x[k][j])%MOD)%MOD;
                }
            }
        }
        return c;
    }
};

時間複雜度爲\(O(nmp)\)優化

常數優化

若是\(a[i][j]=0\),那麼會浪費許多時間來計算\(a[i][j]\)與其餘數的乘積.
只要改一下循環嵌套的順序,並判斷\(a[i][j]\)是否等於\(0\),若是是就直接continue.spa

struct mat {
    long long (*x)[505]=new long long[505][505];//若是矩陣比較小就直接開數組,太大就用指針.
    friend mat operator * (mat a,mat b) {//重載
        mat c;
        for(long long k=1; k<=p; k++) {
            for(long long i=1; i<=n; i++) {
                if(a.x[i][k]==0) continue;//優化
                for(long long j=1; j<=m; j++) {
                    c.x[i][j]=(c.x[i][j]+(a.x[i][k]*b.x[k][j])%MOD)%MOD;
                }
            }
        }
        return c;
    }
};

矩陣快速冪

其實就是把快速冪中的數換成矩陣.指針

矩陣快速冪的應用

斐波那鍥數列 P1962
這是一個矩陣
\(\left\{ \begin{matrix} f(n-1) \\ f(n-2) \end{matrix} \right\}\)
不難很難發現,只要讓它乘上矩陣
\(\left\{ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right\}\)
就能變成\(\left\{ \begin{matrix} f(n) \\ f(n-1) \end{matrix} \right\}\)
因此若是要求\(f(n)\),只需算出\(\left\{ \begin{matrix} f(n-1) \\ f(n-2) \end{matrix} \right\} * \left\{ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right\}^{n-1}\)
結果的第一行第一列就是\(f(n)\).
```cppcode

相關文章
相關標籤/搜索