BSGS 扩展大步小步法解决离散对数问题 (BZOJ 3239: Discrete Logging// 2480: Spoj3105 Mod)

我先转为敬? orz% miskcoo

贴板子 BZOJ 3239: Discrete Logging//2480: Spoj3105 Mod(两道题输入不同,我这里只贴了3239的代码)

CODE

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int p, a, b;
int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
inline int qpow(LL a, LL b, LL c) {
    LL res = 1;
    while(b) {
        if(b&1) res = res * a % c;
        a = a * a % c; b >>= 1;
    }
    return res;
}
map<int, int> myhash;
inline int BSGS(int a, int b, int p) {
    a %= p, b %= p;
    if(p == 1 || b == 1) return 0;
    int cnt = 0; LL tmp = 1; //tmp存a累计下来的系数
    for(int g = gcd(a, p); g != 1; g = gcd(a, p)) {
        if(b % g) return -1;
        p /= g, b /= 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);
    LL now = tmp;
    for(int i = 1; i <= m+1; ++i) {
        now = now * base % p;
        if(myhash.count(now))
            return i * m - myhash[now] + cnt;
    }
    return -1; //仍然无解
}
int main() {
	while(~scanf("%d%d%d", &p, &a, &b)) {
        int ans = BSGS(a, b, p);
        if(~ans) printf("%d
", ans);
        else puts("no solution");
	}
}

原文地址:https://www.cnblogs.com/Orz-IE/p/12039333.html