CF678D 题解

前置芝士:矩阵乘法。

线性递推式:$ g^{n}(x) = Ag^{n - 1}(x) + B $。

那么,可以列出以下式子:

\[\begin{bmatrix} g^n(x) \\ B \end{bmatrix} = \textbf{A}\begin{bmatrix} g^{n - 1}(x) \\ B \end{bmatrix} \]

解得转置矩阵 $ \textbf{A} $ :

\[\textbf{A} = \begin{bmatrix} A & 1 \\ 0 & 1 \end{bmatrix} \]

所以:

\[\begin{bmatrix} g^n(x) \\ B \end{bmatrix} = \textbf{A}^{n}\begin{bmatrix} g^{0}(x) \\ B \end{bmatrix} = \textbf{A}^{n}\begin{bmatrix} x \\ B \end{bmatrix} \]

奉上码风清奇代码一份:

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

typedef long long ll;

const int m = 1e9 + 7;

ll a, b, n, L = 2, x;

inline ll read() {
    ll x = 0;
    bool f = true;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-')
            f = false;
        c = getchar();
    }
    while (isdigit(c)) {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return f ? x : -x;
}

struct Matrix {
    ll M[3][3];
    void clear() memset(M, 0, sizeof(M)); 
    void reset() {
        clear();
        for (int i = 0; i < L; i++)
            M[i][i] = 1;
    }
    Matrix friend operator* (const Matrix &a, const Matrix &b) {
        Matrix Ans;
        Ans.clear();
        for (int i = 0; i < L; i++)
            for (int j = 0; j < L; j++)
                for (int k = 0; k < L; k++)
                    Ans.M[i][j] = (Ans.M[i][j] + a.M[i][k] * b.M[k][j]) % m;
        return Ans;
    }
};

Matrix qp(Matrix a, ll p) {
    Matrix Ans;
    Ans.reset();
    while (p) {
        if (p & 1)
            Ans = Ans * a;
        a = a * a;
        p >>= 1;
    }
    return Ans;
}

int main() {
    a = read();
    b = read();
    n = read();
    x = read();
    Matrix A;
    A.M[0][0] = a, A.M[0][1] = 1;
    A.M[1][0] = 0, A.M[1][1] = 1;
    A = qp(A, n);
    cout << (A.M[0][0] * x + A.M[0][1] * b) % m;
    return 0;
}

双倍经验:P2044 随机数生成器

posted @ 2024-06-26 14:55  Cuset_VoidAldehyde  阅读(19)  评论(0)    收藏  举报