基础篇
- BSGS(baby-step giant-step),即大步小步算法。常用于求解离散对数问题。形象化的说,该算法可以在\(O(\sqrt p)\)的时间内求解\(a^x \equiv b(\mod p)\)(即求解高次同余方程)
- 其中\(a \perp b\)。方程的解\(x\)满足\(0\le x < p\)。(不要求\(p\)为素数)
- 算法描述
- 令\(x=A\lceil {\sqrt p} \rceil-B\)其中\(0 \le {A,B} \le {\lceil {\sqrt p} \rceil}\),则有\(a^{A\lceil{\sqrt p} \rceil-B}\equiv b(\mod p)\),变换,则有\(a^{A\lceil {\sqrt p} \rceil}\equiv b(\mod p)\)
我们已知\(a,b\),所以我们可以先算出等式右边的\(ba^B\)的所有取值,枚举B用hash/map存下来,然后逐一计算\(a^{A\lceil {\sqrt p}\rceil}\),枚举\(A\)寻找是否有与之相等的\(ba^B\),从而我们可以得到所有的\(x\),\(x=A\lceil {\sqrt p}\rceil-B\)
注意到\(A\),\(B\)均小于\(\sqrt p\),所以时间复杂度为\(O(\sqrt p)\),用map则多一个log
ll BSGS(ll a,ll b,ll p){
map<int,int>hash;
ll t=sqrt(p)+1;
for(int i=0;i<t;i++){
ll val=b*qpow(a,i,p);
hash[val]=i;
}
a=qpow(a,t,p);
if(a==0)return b==0?1:-1;
for(int i=0;i<=t;i++){
ll val=qpow(a,i,p);
int j=hash.find(val)==hash.end()?-1:hash[val];
if(j>=0&&i*t-j>=0)return i*t-j;
}
return -1;
}