数论:Extended-BSGS
Update on 2021-11-01: 更新了代码,可能会提升阅读效果吧。
Update on 2022-07-04: 被 @RainFestival Hack 了,更新了代码,已经可以通过。
0. 前置知识 & 废话
逆元。
我的逆元 Blog
1. 普通版 BSGS
要求
其实就是一个分块的思想。
设
注意,这里有一些细节:
- 如果
b 不被d 整除,则直接返回无解。 - 答案可能小于
cnt ,我们必须枚举[0,cnt-1] 的解,看有没有。
于是就转化为了普通的 BSGS 了。
using LL = long long;
int Mod;
int Gcd(int a, int b) { return b ? Gcd(b, a % b) : a; }
void ExGcd(int a, int b, LL &x, LL &y)
{
if (!b) return x = 1, y = 0, void();
ExGcd(b, a % b, y, x), y -= a / b * x;
}
inline int& adj(int &x) { return x += x >> 31 & Mod; }
int qpow(int a, int k)
{
int res = 1;
for (; k; k >>= 1, a = (LL) a * a % Mod)
(k & 1) && (res = (LL) res * a % Mod);
return res;
}
int ExBSGS(int a, int b)
{
a %= Mod, b %= Mod;
if (b == 1 || Mod == 1) return 0;
if (!a) return b ? -1 : 1;
int t, cur = 1, g = 0;
while ((t = Gcd(a, Mod)) != 1)
{
if (b % t) return -1;
++ g, b /= t, Mod /= t, cur = (LL) cur * (a / t) % Mod;
if (cur == b) return g;
}
std::map<int, int> mp;
int B = std::sqrt(Mod) + 1;
LL x, y;
ExGcd(cur, Mod, x, y), x = (x % Mod + Mod) % Mod;
cur = (LL) x * b % Mod;
mp[cur] = 0;
for (int i = 1; i <= B; ++ i) mp[cur = (LL) cur * a % Mod] = i;
int pw = qpow(a, B);
cur = 1;
for (int i = 1; i <= B; ++ i)
if (mp.count(cur = (LL) cur * pw % Mod))
return i * B - mp[cur] + g;
return -1;
}
int main()
{
int a, b;
while (read(a, Mod, b), a || b || Mod)
{
int res = ExBSGS(a, b);
if (~res) write(res, '\n');
else write("No Solution\n");
}
return 0;
}