BSGS

  求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 
}
原文地址:https://www.cnblogs.com/liumengliang/p/12638074.html