BSGS & exBSGS 总结
BSGS
求解 \(a\) 在模 \(m\) 意义下的 \(b\) 离散对数,满足 \(\gcd(a,m)=1\)。
即求最小的非负数 \(x\) 满足 \(a^x \equiv b \pmod m\)。
考虑取 \(t=\lceil \sqrt p \rceil\),令 \(x = i \times t - j\),满足 \(1 \le i \le t,0\le j < t\)。
因为:
两边同乘 \(a^{j}\):
枚举 \(j\),将右边的数插入到哈希表中,最后枚举 \(i\),在哈希表中查询即可,时间复杂度 \(\Theta(\sqrt p)\)。
int bsgs(int a,int b,int p)
{
if(p==1) return 0;
a%=p,b%=p;
if(b&&a==0) return p==1?0:-1;
if(a==b) return 1;
unordered_map<int,int> hs;
int t=ceil(sqrt(1.0*p));
for(int j=0,v=b;j<=t;++j)
{
hs[v]=j;
v=v*a%p;
}
for(int i=1,v=qpow(a,t,p),temp=qpow(a,t,p);i<=t;++i)
{
if(hs.count(v))
{
return i*t-hs[v];
}
v=v*temp%p;
}
return -1;
}
代码细节整理:
-
如果不保证 \(a < p,b<p\),开始时要先模一下。
正确性:对 \(b\) 是显然的,对 \(a\) 来说由于 \((a+kp)^x\) 的 展开中,只有 \(a^x\) 是有贡献的,含有 \((kp)^x\) 的项在模 \(p\) 意义下都是 \(0\)。
-
\(p=1\) 时,\(x=0\)。
-
\(a=b\) 时,\(x=1\) 。
-
如果 \(a \bmod p = 0\),那么 \(b \not = 0\) 且 \(p \not = 1\) 时无解。
exBSGS
求解 \(a\) 在模 \(m\) 意义下的 \(b\) 离散对数,不一定满足 \(\gcd(a,m)=1\)。
即求最小的非负数 \(x\) 满足 \(a^x \equiv b \pmod m\)。
由于 \(a,m\) 不一定互质,考虑化成互质的情况用 BSGS 求解。
同余的一条性质:若 \(a \equiv b \pmod m\),即 \(d = \gcd(a,m)\),那么 $\frac{a}{d} \equiv \frac{b}{d} \pmod {\frac{m}{d}} $
故先取 \(d_1 = \gcd(a,m)\),得到:
如果 \(a,\frac{m}{d_1}\) 仍然不互质,就取 \(d_2 = \gcd(a,\frac{m}{d_1})\) 继续操作,直到 \(a\) 与模数互质:
记 \(A=\frac{a}{\prod_{i=1}^{k}d_i} a^{x-k},M=\frac{m}{\prod_{i=1}^{k}d_i},B=\frac{b}{\prod_{i=1}^{k}d_i}\),二者互质,存在逆元,方程转化为:
用普通 BSGS 求解即可。
int exbsgs(int a,int b,int p)
{
a%=p,b%=p;
if(b==1||p==1) return 0;
int k=0;
int D=1,d,ad=1;
while((d=gcd(a,p))!=1)
{
if(b%d) return -1;
D*=d,b/=d,p/=d;
ad=(ad*a/d)%p;
++k;
if(ad==b) return k;
}
int ans=bsgs(a,b*inv(ad,p)%p,p);
return ans==-1?ans:ans+k;
}
代码细节整理:
- 像普通 BSGS 一样,注意特判 \(p=1,b=1\) 的情况。
- 不断除以 \(d\) 的时候,出现 \(A=B\) 的时候 \(x\) 的最小值就是 \(k\)。

浙公网安备 33010602011771号