bzoj 1420 Discrete Root - 原根 - exgcd - BSGS

题目传送门

  戳我来传送

题目大意

  给定$k, p, a$,求$x^{k}\equiv a \pmod{p}$在模$p$意义下的所有根。

  考虑模$p$下的某个原根$g$。

  那么$x  = g^{ind_{g}x}, a = g^{ind_{g}a}$。

  所以原方程转化为$g^{k\cdot ind_{g}x}\equiv g^{ind_{g}a} \pmod{p}$。

  所以方程等价于$k\cdot ind_{g}x \equiv ind_{g}a \pmod{\varphi(p)}$。

  用exgcd解出$ind_{g}x$的所有可能的解,再用快速幂算出$x$即可。

Code

 /**
* bzoj
* Problem#1420
* Accepted
* Time: 44ms
* Memory: 2032k
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef bool boolean; typedef class HashMap {
private:
static const int M = ;
public:
int ce;
int h[M], key[M], val[M], next[M]; HashMap() { } void insert(int k, int v) {
int ha = k % M;
for (int i = h[ha]; ~i; i = next[i])
if (key[i] == k) {
val[i] = v;
return;
}
++ce, key[ce] = k, val[ce] = v, next[ce] = h[ha], h[ha] = ce;
} int operator [] (int k) {
int ha = k % M;
for (int i = h[ha]; ~i; i = next[i])
if (key[i] == k)
return val[i];
return -;
} void clear() {
ce = -;
memset(h, -, sizeof(h));
}
}HashMap; void exgcd(int a, int b, int& d, int& x, int& y) {
if (!b)
d = a, x = , y = ;
else {
exgcd(b, a % b, d, y, x);
y -= (a / b) * x;
}
} int qpow(int a, int pos, int p) {
int pa = a, rt = ;
for ( ; pos; pos >>= , pa = pa * 1ll * pa % p)
if (pos & )
rt = rt * 1ll * pa % p;
return rt;
} int inv(int a, int n) {
int d, x, y;
exgcd(a, n, d, x, y);
return (x < ) ? (x + n) : (x);
} int p, k, a;
int g; inline void init() {
scanf("%d%d%d", &p, &k, &a);
} HashMap mp;
int ind(int a, int b, int p) {
mp.clear();
int cs = sqrt(p - 0.5), ac = qpow(a, cs, p), iac = b * 1ll * inv(ac, p) % p, pw = ;
for (int i = cs - ; ~i; i--)
iac = iac * 1ll * a % p, mp.insert(iac, i);
for (int i = ; i < p; i += cs, pw = pw * 1ll * ac % p)
if (~mp[pw])
return mp[pw] + i;
return -;
} int top = ;
int fac[];
void getfactors(int x) {
for (int i = ; i * i <= x; i++) {
if (!(x % i)) {
fac[++top] = i;
while (!(x % i)) x /= i;
}
}
if (x != ) fac[++top] = x;
} boolean isroot(int x) {
int pos = p - ;
for (int i = ; i <= top; i++)
if (qpow(x, pos / fac[i], p) == )
return false;
return true;
} inline void solve() {
if (p == || !a) {
printf("1\n0");
return;
}
if (p == )
g = ;
else {
getfactors(p - );
for (g = ; !isroot(g); g++);
} int inda = ind(g, a, p), d, x, y, cir;
exgcd(k, p - , d, x, y);
if (inda % d) {
puts("");
return;
}
cir = (p - ) / d;
x = x * 1ll * (inda / d) % cir;
(x <= ) ? (x += cir) : ();
vector<int> res;
for (; x < p; x += cir)
res.push_back(qpow(g, x, p));
sort(res.begin(), res.end());
printf("%d\n", (signed) res.size());
for (int i = ; i < (signed) res.size(); i++)
printf("%d\n", res[i]);
} int main() {
init();
solve();
return ;
}
上一篇:TRIZ系列-创新原理-26-复制原理


下一篇:RabbitMQ学习笔记(一):安装及Springboot集成