BZOJ 1319: Sgu261Discrete Roots

\[x^k \equiv a \pmod p\]
因为 \(p\) 是质数,所以肯定存在原根 \(g\) 使得 \(g^c\equiv x \pmod p\)
变成求 \[g^{ck}\equiv a \pmod p\]
BSGS 能求出 \(ck=x\) 的值
之后再 exgcd 求出 \(kc \equiv x \pmod {\varphi(p)}\) 的值

#include 

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 gcd(int a, int b) {
    while (b) {
        a %= b;
        std::swap(a, b);
    }
    return a;   
}

const int INF = 0x3f3f3f3f;

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

int BSGS(int a, int b, int mod) {
    a %= 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();
    H.insert(1, 0);
    int inv = qp(a, mod - m - 1, mod);
    for (int i = 1, e = 1; i < m; i++) {
        e = 1LL * e * a % mod;
        if (H[e] == -1)
            H.insert(e, i);
    }
    for (int i = 0; i < m; i++) {
        int x = H[b];
        if (x != -1)
            return i * m + x;
        b = 1LL * b * inv % mod;
    }
    return -1;
}

#define pb push_back

int generator(int p) {
    std::vector factor;
    int phi = p - 1, n = phi;
    for (int i = 2; i * i <= n; i++) {
        if (n % i) continue;
        factor.pb(i);
        while (n % i == 0) n /= i;
    }
    if (n > 1) factor.pb(n);
    for (int i = 2; i <= p; i++) {
        bool flag = 1;
        for (int j = 0; j < factor.size(); j++) {
            if (qp(i, phi / factor[j], p) == 1) {
                flag = 0;
                break;
            }
        }
        if (flag) return i;
    }
    return -1;
}

int exgcd(int a, int b, int &x, int &y) {
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    int g = exgcd(b, a % b, x, y);
    int temp = x;
    x = y;
    y = temp - a / b * y;
    return g;
}

void equ(int a, int b, int c, int &x, int &y) {
    int g = exgcd(a, b, x, y);
    if (c % g) {
        x = y = -INF;
        return;
    }
    a /= g, b /= g, c /= g;
    x = (x % b + b) % b;
    x = 1LL * x * c % b;
    y = b;
}

int main() {
    int mod, k, a;
    scanf("%d%d%d", &mod, &k, &a);
    if (a == 0) {
        puts("1\n0");
        return 0;
    }
    int g = generator(mod);
    int c = BSGS(g, a, mod);
    if (c == -1) {
        puts("0");
        return 0;
    }
    int x, y;
    equ(k, mod - 1, c, x, y);
    if (x == -INF) {
        puts("0");
        return 0;
    }
    //printf("%d %d\n", x, y);
    std::vector ans;
    for ( ; x < mod - 1; x += y) {
        ans.push_back(qp(g, x, mod));
    }
    std::sort(ans.begin(), ans.end());
    printf("%d\n", (int)ans.size());
    for (int i = 0; i < ans.size(); i++)
        printf("%d\n", ans[i]);
    return 0;
}

你可能感兴趣的:(BZOJ 1319: Sgu261Discrete Roots)