BSGS算法是一种用于解决离散对数问题的算法,它的全称是Baby Step Giant Step,意为小步大步。然而我并不知到为什么要叫这个名字

离散对数问题

假设有一个同余方程axb(modm),其中a,b,m都是给定的整数,am互素。如何求解x的值?

第一个想法可能是暴力枚举,将x0开始枚举到m1,直到找到一个满足方程的x。时间复杂度是O(m),如果m很大就挂了。

BSGS算法

既然暴力不行,那么我们就要想办法降低时间复杂度。BSGS算法就是一种优化的算法,它的时间复杂度是O(m)。它的思想也很简单。

首先我们令x=AmB,其中A,B是两个整数且0A,Bm。那么原方程就变成了aAmBb(modm),即aAmbaB(modm)

我们可以将方程分解为两个方程:

{cbaB(modm)aAmc(modm)

对于第一个方程,我们可以从1m枚举B的值,用一个map存对应B的值。对于第二个方程,依旧从0m枚举A的值,然后在map中查找是否有相等的baB,获取B的值,最后得到x的值。

cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//a^x=b(mod p)
LLI BSGS(int a,int b,int p){
if(a%p==0||b%p==0){//特殊情况
if(b%p==0&&a%p==0)return 1;
else return -1;
}

map<LLI,LLI> mp;
LLI cur=1,t=sqrt(p)+1;
for(LLI B=1;B<=t;++B){
cur=cur*a%p;
mp[b*cur%p]=B;
}
LLI now=cur;
for(LLI A=1;A<=t;++A){
if(mp[now])return A*t-mp[now];
now=now*cur%p;
}return -1;
}