bsgs算法
一、算法简析
BSGS算法(Baby Step Giant Step),可以求解高次同余方程。
条件
正整数 \(a,b,p\),且 \(a\) 与 \(p\) 互质,求满足 \(a^x\equiv b~(mod~p)\) 的最小非负整数 \(x\)。
化简
由拓展欧拉定理,得到
由题意,\(a\) 与 \(p\) 互质,满足欧拉定理,得
同乘 \(a^{x~mod~\varphi(p)}\),得
因为 \(\varphi(p)<p\),所以仅考虑 \(x\in[0,p]\),能找到答案。直接暴力的效率为 \(O(p)\)。
BSGS算法
前期处理
步骤一
令 \(x=i\times m-j\),其中 \(m=\lceil \sqrt{p} \rceil\),\(i\in[1,m]\),\(j\in[0,m-1]\)。
\(x\) 得取值范围为:
- 若 \(i=1,j=m-1\),则 \(x\) 取最小值。
- 若 \(i=m,j=0\),则 \(x\) 取最大值。
所以,\(x\in[1,p]\)。因此,对于 \(x=0\) 需要特判。
步骤二
此时,同余方程变为 \(a^{i\times m-j}\equiv b~(mod~p)\),同乘 \(a^j\),得
分别计算两边得式子,之后相互匹配即可。
算法详情
- 遍历 \(j\in[0,m-1]\),计算 \(a^j~(mod~p)\),用哈希表记录 \((a^j, j)\)。如果 \(a^j\) 重复,则用更大的 \(j\) 替代。(因为求 \(x\) 的最小值)
- 遍历 \(i\in[1,m]\),计算 \((a^m)^i~(mod~p)\),在哈希表中查找是否有对应的 \(a^j\)。若找到这样的 \(j\),则得到答案 \(x=i\times m-j\)。
此处有个细节:
我们找到的 \(i\) 和 \(j\) 满足同余方程 \((a^m)^i\equiv b\times a^j~(mod~p)\),但要求的是 \(a^{i\times m-j}\equiv b~(mod~p)\)。这里,两边同除了 \(a^j\)。对于除法运算,只有 \(a\) 与 \(p\) 互质 时,才成立。(题目中给出了互质关系)
注意点
对于BSGS算法,必须强调 \(a\) 与 \(p\) 互质。算法中,化解(欧拉定理)和得到最终结果(除法运算)都要用到该条件。
二、Code
// 求最小x,使 a^x==b (mod p)
ll bsgs(ll a, ll b, ll p)
{
a %= p, b %= p;
if (b == 1) return 0; // 特判,x=0的情况
ll m = ceil(sqrt(p));
unordered_map<int, int> hash; // 记录<ba^j, j>
ll t = b;
hash[t] = 0; // j=0
for (int j = 1; j < m; ++j)
{
t = t * a % p;
hash[t] = j;
}
ll mi = 1;
for (int i = 1; i <= m; ++i) // 计算a^m
mi = mi * a % p;
t = 1;
for (int i = 1; i <= m; ++i) // 计算(a^m)^i
{
t = t * mi % p;
if (hash.find(t) != hash.end())
return i * m - hash[t];
}
return -1; // 不存在x
}
相关题目
P3846 [TJOI2007] 可爱的质数/【模板】BSGS
题目给出的数据范围,\(2\le b,n<p<2^{31}\),暗示 \(b\) 与 \(p\) 互质。
完