BSGS
求解 (a^x equiv b pmod{p},a ot p)。
由欧拉定理 (a^{varphi(m)} equiv 1 pmod{m},a ot m) 得方程的解取值范围为 ([1,varphi(m)])。
设 (x=A sqrt p - B,0 leqslant A,B leqslant sqrt p),得:
[largeegin{aligned}
a^{A sqrt p - B} &equiv b pmod{p} \
a^{A sqrt p} &equiv a^Bb pmod{p}
end{aligned}
]
先枚举 (B) 算出 (a^Bb) 的所有取值,然后枚举 (A) 算出 (a^{A sqrt p}),查找是否有相等的 (a^Bb)。复杂度为 (O(sqrt p))。
防止出现负数解,(A) 的枚举范围为 ([1,sqrt p]),(B) 的枚举范围为 ([0,sqrt p])。
为保证正确性,(sqrt p) 要上取整。
扩展BSGS
求解 (a^x equiv b pmod{p}),不保证 (a ot p)。
因为此时不保证 (a ot p),不一定存在逆元,所以不能直接做。
设 (g_1=gcd(a,p)),方程同除 (g_1) 得:
[large frac{a}{g_1}a^{x-1} equiv frac{b}{g_1} pmod{frac{p}{g_1}}
]
若 (a ot ot frac{p}{g_1}),就设 (g_1=gcd(a,frac{p}{g_1})),方程同除 (g_2) 得:
[large frac{a^2}{g_1g_2}a^{x-2} equiv frac{b}{g_1g_2} pmod{frac{p}{g_1g_2}}
]
设变换了 (k) 次,直到 (a ot frac{p}{g_1g_2 dots g_k}),在过程中,若 (g_k ot mid frac{b}{g_1g_2 dots g_{k-1}}) 则方程无解。
设 (G= prodlimits_{i=1}^k g_i),得:
[large frac{a^k}{G}a^{x-k} equiv frac{b}{G} pmod{frac{p}{G}}
]
由 (a ot frac{p}{G}) 得 (frac{a^k}{G} ot frac{p}{G}),此时 (frac{a^k}{G}) 存在逆元,得:
[large a^{x-k} equiv frac{b}{a^k} pmod{frac{p}{G}}
]
然后直接应用 (BSGS) 求解即可。
注意到解可能小于等于 (k),因此还需进行验证。
ll bsgs(ll a,ll b,ll p)
{
ll s=ceil(sqrt(p)),v=b,val;
for(int i=0;i<=s;++i,v=v*a%p) h[v]=i;
v=val=qp(a,s,p);
for(int i=1;i<=s;++i,v=v*val%p)
if(h.count(v))
return i*s-h[v];
return -1;
}
ll exbsgs(ll a,ll b,ll p)
{
a%=p,b%=p;
if(b==1||p==1) return 0;
ll g,cnt=0,mul=1,v=a;
for(int i=1;i<=30;++i,v=v*a%p)
if(v==b)
return i;
while((g=exgcd(a,p))!=1)
{
if(b%g!=0) return -1;
cnt++,b/=g,p/=g,mul=mul*(a/g)%p;
}
ll ans=bsgs(a,b*inv(mul,p)%p,p);
if(~ans) return ans+cnt;
return -1;
}