其他分享
首页 > 其他分享> > 归档:220813 | 社恐铁锹的第一次新知讲授:矩阵快速幂

归档:220813 | 社恐铁锹的第一次新知讲授:矩阵快速幂

作者:互联网

铁锹:呃,其实我的名字是英文缩写,不是铁锹,你们不要再给我乱起外号了


什么是矩阵?

一个 \(n\times m\) 的矩阵是由数组成的 \(n\) 行 \(m\) 列的方阵。

什么是矩阵乘法?

假设有三个矩阵 \(A, B, C\),其中 \(A\) 的列数与 \(B\) 的行数相等(假设为 \(n\))。若 \(C=A\times B\),那么 \(C_{i,j}=\sum\limits_{k=1}^n A_{i,k}\times B_{k,j}\),其中 \(C\) 的行数与 \(A\) 的行数相等,\(B\) 的列数与 \(C\) 的列数相等。

什么是矩阵快速幂?

把普通快速幂的底数换成矩阵。

铁锹:呃我要讲的就是这些,同学们可以开始做题了。


呃呃,所以模拟一下这个过程就好了?

namespace Matrix {
const int maxn = 25;
template<const int mod>
class Mat {
private:
    int n, m;
public:
    int a[maxn][maxn];
    Mat () {}
    Mat (int N, int M, bool type = 0) {
        n = N, m = M;
        memset(a, 0, sizeof (a));
        if (type) {
            for (int i = 1; i <= n; ++i)
                a[i][i] = 1;
        }
    }
    int* operator[] (int q) {
        return a[q];
    }
    const int* operator[] (int q) const {
        return a[q];
    }
    Mat operator* (const Mat &q) const {
        Mat res(n, q.m);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= q.m; ++j) {
                for (int k = 1; k <= m; ++k) {
                    (res[i][j] += (a[i][k] 
                        * q[k][j] % mod + mod)
                        % mod) %= mod;
                }
            }
        }
        return res;
    }
    Mat& operator*= (const Mat &q) {
        return (*this) = (*this) * q;
    }
    Mat operator^ (const int q) const {
        int y = q;
        Mat res(n, n, 1), x(*this);
        while (y) {
            if (y & 1)
                res *= x;
            x *= x;
            y >>= 1;
        }
        return res;
    }
    Mat& operator^= (const int &q) {
        return (*this) = (*this) ^ q;
    }
};
} // namespace Matrix

CF450B - Jzzhu and Sequences

游戏的第一关都会放一个稀奇古怪的东西让新手入门。

——我也不知道是哪位 TFer 说的

我看了大半天没看懂样例最后发现不是斐波那契???

那也和斐波那契一样啊。

我们都知道,斐波那契的加速矩阵是这样的:

\[[f_{i - 1},f_i]=[f_i,f_{i + 1}]\times\begin{bmatrix}0&1\\1&1 \end{bmatrix} \]

那我们把 \(f_{i-1}\to f_{i+1}\) 的系数改成减就好了。

namespace XSC062 {
using namespace fastIO;
using namespace Matrix;
const int mod = 1e9 + 7;
int x, y, m;
Mat<mod> A, B;
int main() {
    read(x);
    read(y);
    read(m);
    if (m == 1) {
        printf("%lld", (x % mod + mod) % mod);
        return 0;
    }
    if (m == 2) {
        printf("%lld", (y % mod + mod) % mod);
        return 0;
    }
    A = Mat<mod>(1, 2);
    B = Mat<mod>(2, 2);
    A[1][1] = x;
    A[1][2] = y;
    B[1][2] = -1;
    B[2][1] = B[2][2] = 1;
    A *= (B ^= (m - 2));
    printf("%lld", A[1][2]);
    return 0;
}
} // namespace XSC062

标签:return,Mat,社恐,namespace,220813,矩阵,int,新知,mod
来源: https://www.cnblogs.com/XSC062/p/16590168.html