分析题意,即求 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;
}