BSGS算法,原名Baby Steps Giant Steps,又名大小步算法,拔山盖世算法,北上广深算法——by SLYZoier,数论基本算法之一。
给定 a,b,p ,求最小的非负整数 x ,满足 ax≡b(modp)
这就是经典的BSGS算法,方法如下:
令 x=im−j , m=⌈p√⌉ ,则 aim−j≡b(modp)
移项,得 (am)i≡baj(modp)
首先,从 0−m 枚举 j ,将得到的 baj 的值存入hash表;
然后,从 1−m 枚举 i ,计算 (am)i ,查表,如果有值与之相等,则当时得到的 im−j 是最小值。
1、讨论无解的情况?
方程有解的充要条件是 p 为质数且 (a,p)=1
可以发现这是费马小定理的条件,会在问题2中讨论。
2、为什么 m 取 ⌈p√⌉ 就可以?
我们先考虑枚举的思路:如果要是枚举 x 的值的话应该何时停止?
首先证明: akmodp≡ak(modp)
ak−mp≡ak(modp)
akamp≡ak(modp)
即使 (ap)m≡1(modp)
由费马小定理知当 p 为质数且 (a,p)=1 时 ap≡1(modp)
推出 p 为质数且 (a,p)=1 这个条件,并证明结论 akmodp≡ak(modp)
即我们得到:枚举 x 的话枚举到 p 即可。
所以使 im−j<=p ,即 m=⌈p√⌉ , i,j 最大值也为m。
3、为什么第一个枚举到的 im−j 是最小值?
首先要明确的一点是,枚举 j 时算出来的值有可能重复,那么我们在hash表里就要用新的值覆盖原来的值。正确性显而易见,要保证 im−j 最小,就要保证 j 最大。
为什么枚举到最小的 i 就是最小值呢?思考每枚举到一个 i , im 的值实际上是在原来的基础上增加了 m ,而 j 的范围是 [0,m] ,也就是说 im 增加的幅度一定比 j 增加的幅度大,从而保证了首先枚举到的一定是最小值。
4、为什么从 0−m 枚举 j ,而从 1−m 枚举 i ?
i 不能为0,否则 im−j 有可能出现负数的情况