1574. 云烟的大炮对决

分析题意,即求 a^x \equiv b(\bmod p) 的最小整数解 x 。不可以用快速幂枚举,时间复杂度为 \Omicron(p\sqrt p) 。可以使用数论算法的 BSGS 算法直接求解本题。BSGS 的适用条件为 a\bot p 。若 a\not\bot p ,则可以发现 a^x\bmod p 恒为 a ,即 a=b ,则此时显然也有 x=1 为答案。时间复杂度为 \Omicron(\sqrt p)

注意最后输出 x^x\bmod p 时需要使用快速幂算法,时间复杂度也为 \Omicron(\sqrt p)

BSGS算法具体请参考这篇文章。本题也可以使用 exBSGS 算法求解。

参考代码如下:

#define mn 1000700 #define mod 1000007 struct hasht { ll mp[mn], hsh[mn]; //避免关键字冲突map,hash il ll find(ll x) //拉链法构造散列表 { ll t = x % mod; for (; mp[t] != x && mp[t] != -1; (t += 107) %= mod) ; return t; } il void insert(ll x, ll i) { ll f = find(x); mp[f] = x, hsh[f] = i; } il bool in(ll x) { return mp[find(x)] == x; } il ll get_hash(ll x) { return hsh[find(x)]; } il void init() { memset(hsh, -1, sizeof hsh), memset(mp, -1, sizeof mp); } } h; ll qpow(ll a, ll b, ll p) { ll r = 1; for (; b; b >>= 1, (a *= a) %= p) { if (b & 1) { (r *= a) %= p; } } return r; } ll a, b, p, m, s; //long long signed main() { sc(p), sc(a), sc(b); h.init(); m = ceil(sqrt((db)p)) + 1, s = 1; for (ll i = 1; i <= m; ++i) { h.insert(b, i); s = (1LL * s * a) % p, b = (1LL * a * b) % p; } a = s; for (ll i = 1; i <= m; ++i) { if (h.in(a)) { ll x = i * m - h.get_hash(a) + 1; printf("flag{%lld}", qpow(x, x, p)); return 0; } a = (1LL * a * s) % p; } return 0; }