矩陣快速冪

矩陣快速冪

\(emmm\),考試上面見到的,以前聽顏神講過一遍但是沒有聽懂,現在看一下還是比較妙妙的

矩陣乘法

矩陣乘法是什麼?

簡而言之就是

\[c_{ij} = \quad\sum_{k=1}^na_{ik} *b_{kj} \]

舉個簡單的例子

\[ \left\{ \begin{matrix} 14 \\ 32 \\ 50 \end{matrix} \right\} = \left\{ \begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9 \end{matrix} \right\} * \left\{ \begin{matrix} 1\\ 2 \\ 3 \end{matrix} \right\} \]
真簡單哇!(光速溜

\(emmm\),這就是矩陣乘法的定義

下面給出詳細代碼

int n;//矩陣大小

void Up(int &x, int y) { x = (x + y) % mod; }//簡單定義 += 

struct Matrix
{
    int a[n][n];//矩陣
    friend Matrix operator *(const Matrix x, const Matrix y)//定義矩陣類型的乘法
    {
        Matrix c;//定義新的矩陣用來存儲結果
        memset(c.a, 0, sizeof(c.a));//初始化
        for(int i = 0; i < n;i ++)//進行枚舉
            for(int j = 0; j < n;j ++)
                for(int k = 0; k < n;k ++)
                    Up(c.a[i][j], x.a[i][k] * y.a[k][j] % mod);//相乘 
        return c;//返回答案矩陣
    }
};

快速冪

快速冪還算比較簡單了的吧

反正我一開始只是知道快速冪而已

簡單來說,通過二進制位來實現

\(2^0= 2^0\)

\(2^1 = 2^1\)

\(2^2=2^2\)

\(2^3 = 2^2*2\)

\(2^4 =2^4\)

\(2^5 = 2^4*2\)

\(2^6 = 2 ^ 4 * 2 ^ 2\)

\(2^7 = 2^4*2^2*2\)

所以我們可以看出來的是

二進制位上我們現在只有當某一位是1的時候才乘

舉個例子

\[2^{15} =2^{1111} = 2^{1000}*2^{100}*2^{10}*2^{1}=2^8*2^4*2^2*2^1 \]

所以相對來說比較好理解

原來\(O(b)\)複雜度一下降低到了\(O(logb)\)

所以快速冪是一種優化的手段

下面貼上代碼

inline int pow(int a,int b)
{
    int r=1,base=a;
    while(b)
    {
        if(b&1) r*=base;//如果當前位是1,那麼直接相乘
        base*=base;//不管是什麼數字下一位都需要再乘一次(2的倍數)
        b>>=1;//移到下一位
    }
    return r;//返回結果
}

矩陣乘法快速冪

void Up(int &x, int y) { x = (x + y) % mod; }//簡單定義+=

struct Matrix
{
    int a[n][n];
    friend Matrix operator *(const Matrix x, const Matrix y)//定義矩陣乘法
    {
        Matrix c;
        memset(c.a, 0, sizeof(c.a));
        for(int i = 0; i < n; i ++)
            for(int j = 0; j < n; j ++)
                for(int k = 0; k < n; k ++)
                    Up(c.a[i][j], x.a[i][k] * y.a[k][j] % mod); 
        return c;
    }
};

Matrix Qpow(Matrix x, int timer)//矩陣快速冪
{
    Matrix base;//定義結果矩陣
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            base.a[i][j] = 0;
    for(int i = 0; i < n; i ++) base.a[i][i] = 1;
    for(; timer; timer >>= 1, x = x * x)
        if(timer & 1) base = base * x;
    return base;
}

\(mod\)是一個簡單的模數,考試的時候一般要求取模運算

Luogu P1962 斐波那契數列

\(emmm\)可以說是矩陣快速冪的基礎練習題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章