BSGS算法
给定一个质数 p,以及正整数 a,b,求满足同余方程 \(a^x=b(mod p)\)的最小非负整数x,无法满足时输出-1.
如果只是简单的枚举 x
,那么要想得出结论,由于循环节最大为 \(p-1\)(欧拉定理),就需要枚举 0~p-1
去验证答案,当 p 的数量级达到 时,这种枚举显然不能满足算法时间复杂度的需求了。
推导过程
首先令\(x=A\times \lceil \sqrt{p} \rceil - B\),其中,\(0\leq A,B \leq \lceil \sqrt{p} \rceil\),将其代入方程得:\(a^{A\times \lceil \sqrt{p} \rceil - B}=b(mod p)\),
移项得\(a^{A\times \lceil \sqrt{p} \rceil}=b\times a^B(mod p)\)
分析这个方程可知:a,b已知,枚举A,B来计算方程的解.
先枚举B,将方程右边的结果存入哈希表中,在枚举A,若出现的值存在于哈希表中,可以通过\(x=A\times \lceil \sqrt{p} \rceil - B\),
得到方程的解.
时间复杂度\(O(\sqrt{p} \log{\sqrt{p}})\)
(对于引入中的问题,只要在枚举 A 的过程中发现值与右端中某个值相等,那么就可以直接返回 ,因为在 A 的增大过程中, 是逐渐增大的,因此第一次找到相等情况的就是答案)
ll bsgs(ll a, ll b, ll mod)
{
map<ll, ll> mp;
ll cur = 1, t = sqrt(mod) + 1;
for(int B = 1; B <= t; B++)
{
cur = cur * a % mod;
mp[b * cur % mod] = B;
}
ll now = cur;
for(int A = 1; A <= t; A++)
{
if(mp[now])
return (ll)A * t - mp[now];
now = now * cur % mod;
}
return -1;
}