【算法】快速幂与矩阵快速幂

普通快速幂

思想

\(a ^ b = a\) 的所有 \(b\) 的二进制位为 \(1\) 的位在十进制下表示的数的次方。

例子

\(3 ^ {11}\)

首先 \(11\) 在二进制下的表示为 \((1011)_2\), 依次表示 \(8, 2, 1\)

\(3 ^ {11}\) = \(3^8 \times 3 ^ 2 \times 3 ^1\)

所以我们发现,\(a ^ b = a\) 的所有 \(b\) 的二进制位为 \(1\) 的位在十进制下表示的数的次方。

于是我们发现如果 \(b\) 的(当前)第一个二进制位为一,则将答案乘上这位表示的数,并将 \(b\) 右移一位,即抛掉这刚刚乘出来的数,并重复这一过程直到 \(b = 0\)
上代码!

#include <bits/stdc++.h>
using namespace std;

long long a, b, k;

long long qpower(long long a, long long b, long long c) {
    long long ans = 1, sum = a;

    while (b > 0) {
        if (b & 1) ans *= sum; ans %= c;
        sum *= sum;
        sum %= c;
        b >>= 1;
    }
    return ans%c;
}

int main() {
    scanf("%lld %lld %lld", &a, &b, &k);
    printf("%lld^%lld mod %lld=%lld", a, b, k, qpower(a, b, k));
    return 0;
}

矩阵快速幂

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int MOD = 1e9 + 7;

ll n, k2;

struct mrt{
    ll m[101][101];
    void read() {
        for (int i = 1; i <= 100; ++i) {
            for (int j = 1; j <= 100; ++j) m[i][j] = 0;
        }
        int x;
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= n; ++j) scanf("%d", &x), m[i][j] = x;
    }
    void print() {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) printf("%d ", m[i][j]);
            puts("");
        }
    }
};

mrt s, e, y;

mrt mc(mrt a, mrt b) {
    mrt c;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j) c.m[i][j] = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            for (int k = 1; k <= n; ++k) {
                c.m[i][j] = (c.m[i][j] + (a.m[i][k] * b.m[k][j]) % MOD) % MOD;
            }
        }
    }
    return c;
}
mrt mqpower(mrt a, ll b) {
    if (b <= 1) return a;
    mrt ans;
    for (int i = 1; i <= n; ++i) {
        ans.m[i][i] = 1;
    }
    while (b > 0) {
        if (b & 1) ans = mc(a, ans);
        a = mc(a, a);
        b >>= 1;
    }
    return ans;
}

int main() {
    scanf("%lld %lld", &n, &k2);
    s.read();
    mqpower(s, k2).print();
    return 0;
}

只需要把乘号变成矩阵的运算就行了。
矩阵运算公式:
\[A \times B = C\]

确切的说是:

\[C_{i, j} = \sum _k^n A_{i, k} \times B_{k,j}\]
\(n\) 为矩阵大小
矩阵 \(C\) 的大小为 \(A\) 的宽与 \(B\) 的长

值得一提的是应先将快速幂中返回的矩阵赋值为单位矩阵(对角线为 \(1\) )再计算 \(k\) 次快速幂

如何构造矩阵

网址
例题

猜你喜欢

转载自www.cnblogs.com/blackwhitetony/p/10344709.html