BSGS

\(BSGS\)

\(BSGS\)\(baby-step\space giant-step\)),即大步小步算法,常用于求解离散对数问题。
形式化地说,该算法可以在 \(O(\sqrt{p})\) 的时间内求解 \(a^x \equiv b \pmod p\)\(a\perp p\)) 方程的解 \(x\) 满足 \(0 \le x < p\)。(在这里需要注意,只要 \(a\perp p\) 就行了,不要求 \(p\) 是素数)

\(BSGS\)

\(t=\lceil \sqrt p \rceil\)\(x = i\cdot t- j\),其中 \(0\le i,j \le t\),则有 \(a^{i\cdot t -j} \equiv b \pmod p\),变换得 \(a^{i\cdot t} \equiv b\cdot a^j \pmod p\)

先枚举\(j\),算出等式右边的 \(b\cdot a^j\) 的所有取值,然后枚举\(i\),计算 \(a^{i\cdot t}\),看是否有与之相等的 \(b\cdot a^j\),从而得到 \(x\)

由于 \(0\le i,j \le t=\lceil \sqrt p \rceil\),所以复杂度为\(O(\sqrt{p})\)

il int bsgs(int a,int b,int p){
    if(1%p==b%p) return 0;
    int t=ceil(sqrt(p)),s=1,ss=0;
    mp.clear();
    for(ri int i=0;i<t;++i){
        if(s==b) return i; // a^0=1
        mp[s*b%p]=i,s=s*a%p;
    }
    ss=s;
    for(ri int i=1;i<=t;++i){
        if(mp.count(ss)) return i*t-mp[ss];
        ss=ss*s%p;
    }
    return -1;
}

\(exBSGS\)

对于\(a^x \equiv b \pmod p\)\(a,p\)不一定互质,在模 \(p\) 意义下 \(a\) 不一定存在逆元,于是我们想办法让他们变得互质
我们设 \(d_1=\gcd(a,p)\),如果 \(d_1\nmid b\),则原方程无解。否则我们把方程同时除以 \(d_1\),得到

\[\frac{a}{d_1}\cdot a^{x-1}\equiv \frac{b}{d_1} (\mod \frac{p}{d_1}) \]

如果\(a\not\perp \frac{p}{d_1}\),就继续除,设 \(d_2=\gcd\left(a,\frac{p}{d_1}\right)\) ,如果 \(d_2\nmid \frac{b}{d_1}\),则方程无解;否则同时除以 \(d_2\) 得到

\[\frac{a}{d_1\cdot d_2}\cdot a^{x-2}\equiv \frac{b}{d_1\cdot d_2} (\mod \frac{p}{d_1\cdot d_2}) \]

重复上述操作,直到\(a\perp \frac{p}{d_1\cdot d_2 \dots d_k}\)

il int exbsgs(int a,int b,int p){
    int d=1,nxtd=0,as=0,xi=1%p,k=0;
    while(1){
        nxtd=gcd(xi*a%p,p);
        if(d==nxtd) break;
        if(xi==b) return k;
        ++k,xi=xi*a%p,d=nxtd;
    }
    if(b%d) return -1;
    xi/=d,p/=d,b/=d;
    b=b*inv(xi,p)%p,as=bsgs(a,b,p);
    return (~as)?k+as:as;
}

edit

posted @ 2023-01-28 16:44  雨夜风月  阅读(80)  评论(0编辑  收藏  举报