求a^x≡b(mod p)的一组解,p≤10^9且为质数
不妨设a^1,a^2....a^sqrt(p)为1号序列
a^sqrt(p)+1...a^2sqrt(p)为2号序列
以此类推
首先我们枚举a^1,a^2....a^sqrt(p)( mod p)即1号序列mod p的值
如果有,就说明找到了一组解
如果没有:
再枚举a^sqrt(p)+1...a^2sqrt(p)即2号序列mod p 的值,如果在这一序列中有满足条件的
即a^(sqrt(p)+i)≡b (mod p),那么在1号序列中一定有a^i≡b/sqrt(p) (mod p)
也就是说,要寻找2号序列中是否有满足mod p等于b的数,等价于在1号序列中寻找满足mod p等于 b/sqrt(p)
进而,对n号序列寻找满足条件的数,就等价于在1号序列中寻找mod p等于b/((n-1)*sqrt(p))的数
在1号序列的寻找可先排序再二分寻找
如果不懂快速幂请转:https://blog.csdn.net/Harington/article/details/87602682
如果不懂逆元的概念请转:https://www.cnblogs.com/liumengliang/p/12548269.html
如果想探求怎样求逆元请转:https://www.cnblogs.com/liumengliang/p/12559051.html
下面是伪代码:
int bsgs(int a,int b,int p)//a^x%p=b { int sp=int(sqrt(p)); z[0]=1;//z数组存1号序列的值 for(int i=1;i<sp;i++)//在这里1号序列设为0~sqrt(p)-1 z[i]=1ll*z[i-1]*a%p; for(int i=0;i<sp;i++) if(z[i]%p==b) return i;//先从1号序列中寻找 sort(z,z+sp);//先把1号序列排好序,方便下面二分使用 int asp=ksm(a,sp,p);//下面的序列是从a^sqrt(p)开始的 //所以用asp表示a^sqrt(p)%p的值 for(int i=2,l=sp,r=sp+sp-1;l<=n;l+=sp,r+=sp,i++) { //从2号序列开始,直到找完n号序列(即找完an) //如果有就找到了,没有就说明该方程没有合法的解 int div=ksm(asp,i-1,p) div=ksm(div,p-2,p); //模意义下的除法是求逆元 int v=1ll*b*div%p; binary(); //在1号序列中二分寻找满足mod p=b/((n-1)*sqrt(p))的数 //不在代码中写了 } return -1;//如果没有合法的解,返回-1 }