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 <bits/stdc++.h>

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<int> 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<int> 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;
}
posted @ 2020-02-12 19:59  Mrzdtz220  阅读(123)  评论(0)    收藏  举报