BZOJ 3122: [Sdoi2013]随机数生成器

\(X_{i+1}\equiv aX_i+b \pmod p\)
\(X_{i+1}+z \equiv a(X_i+z) \pmod p\)
其中 \(z \equiv b(a-1)^{-1} \pmod p\)
即求 \((X_1+z)a^{n-1} - z \equiv t \pmod p\) 的最小自然数解 \(n\)
特判几种情况
一,第一天就看的那一页
二、\(a=0\) 之后每天都看同一页 \(b\)
三、\(a=1\),当 \(b\)\(0\) 时,也是每一天都看同一页,\(b\) 不为 \(0\) 时为等差数列,求同余方程的解

#include <bits/stdc++.h>

const int INF = 0x3f3f3f3f;

int qp(int a, int b, int p) {
    a %= p;
    if (!a) return 0;
    int res = 1;
    while (b > 0) {
        if (b & 1) res = 1LL * res * a % p;
        a = 1LL * a * a % p;
        b >>= 1;
    }
    return res % p;
}

int gcd(int a, int b) {
    while (b) {
        a %= b;
        std::swap(a, b);
    }
    return a;
}

struct Ha {
    static const int mod = 1e6 + 7;
    int head[mod + 5], cnt;
    struct E {
        int x, ans, ne;
    } e[mod << 1];
    void clear() {
        cnt = 1;
        memset(head, 0, sizeof(head));
    }
    Ha() { clear(); }
    void insert(int x, int v) {
        int u = x % mod;
        e[++cnt].x = x; e[cnt].ans = v; e[cnt].ne = head[u]; head[u] = cnt;
    }
    int operator[](const int &k) const {
        int u = k % mod;
        for (int i = head[u]; i; i = e[i].ne)
            if (e[i].x == k) return e[i].ans;
        return -1;
    }
} H;

int BSGS(int a, int b, int mod) {
    if (mod == 1) return 0;
    if (a >= mod) a %= mod;
    if (b >= mod) b %= mod;
    if (a == 0) return b == 0 ? 1 : -1;
    if (b == 1) return 0;
    int m = ceil(sqrt(mod + 0.5));
    H.clear();
    for (int B = 0; B < m; B++) {
        H.insert(b, B);
        b = 1LL * b * a % mod;
    }
    int base = qp(a, m, mod), cur = base;
    for (int A = 1; A <= m + 1; A++) {
        int B = H[cur];
        if (~B) return A * m - B;
        cur = 1LL * cur * base % mod;
    }
    return -1;
}

int solve() {
    int p, a, b, x1, t;
    scanf("%d%d%d%d%d", &p, &a, &b, &x1, &t);
    if (x1 == t) return 1;
    if (a == 0) {
        if (b == t) return 2;
        return -1;
    }
    if (a == 1) {
        if (b == 0) return -1;
        t -= x1;
        if (t < 0) t += p;
        t = 1LL * t * qp(b, p - 2, p) % p;
        return t + 1;
    }
    int z = 1LL * b * qp(a - 1, p - 2, p) % p;
    x1 += z;
    if (x1 >= p) x1 -= p;
    t += z;
    if (t >= p) t -= p;
    b = 1LL * t * qp(x1, p - 2, p) % p;
    int ans = BSGS(a, b, p);
    if (ans == -1) return -1;
    return ans + 1;
}

int main() {
    //freopen("ans.out", "w", stdout);
    int T;
    scanf("%d", &T);
    while (T--) 
        printf("%d\n", solve());
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/12301503.html
今日推荐