BZOJ 2242 / Luogu P2485 [SDOI2011]计算器 (BSGS)

type 1type 1 就直接快速幂
type 2type 2 特判+求逆元就行了.
type 3type 3 BSGS板

CODE

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline LL qpow(LL a, LL b, LL c) {
    LL re = 1;
    while(b) {
        if(b & 1) re = re * a % c;
        a = a * a % c; b >>= 1;
    }
    return re;
}
int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
map<int, int>myhash;
inline int Baby_Step_Giant_Step(int a, int b, int p) {
    if(p == 1) return 0;
    a %= p, b %= p;
    if(b == 1) return 0;
    int cnt = 0; LL tmp = 1;
    for(int g = gcd(a, p); g != 1; g = gcd(a, p)) {
        if(b % g) return -1;
        b /= g, p /= g, tmp = tmp * (a/g) % p;
        ++cnt;
        if(b == tmp) return cnt;
    }
    myhash.clear();
    int m = int(sqrt(p) + 1);
    LL base = b;
    for(int i = 0; i < m; ++i) {
        myhash[base] = i;
        base = base * a % p;
    }
    base = qpow(a, m, p);
    for(int i = 1; i <= m+1; ++i) {
        tmp = tmp * base % p;
        if(myhash.count(tmp))
            return i*m - myhash[tmp] + cnt;
    }
    return -1;
}
inline void solve1(int a, int b, int p) {
    printf("%d
", qpow(a, b, p));
}
inline void solve2(int a, int b, int p) {
    a %= p, b %= p;
    if(!a) {
        if(!b) puts("0");
        else puts("Orz, I cannot find x!");
    }
    else printf("%d
", int(1ll * b * qpow(a, p-2, p) % p));
}
inline void solve3(int a, int b, int p) {
    int ans = Baby_Step_Giant_Step(a, b, p);
    if(~ans) printf("%d
", ans);
    else puts("Orz, I cannot find x!");
}
int main() {
	int a, b, p, T, type;
	scanf("%d%d", &T, &type);
	while(T--) {
        scanf("%d%d%d", &a, &b, &p);
        if(type == 1) solve1(a, b, p);
        else if(type == 2) solve2(a, b, p);
        else solve3(a, b, p);
	}
}
原文地址:https://www.cnblogs.com/Orz-IE/p/12039311.html