[15/08/19] BSGS & ex-BSGS 学习笔记

  BSGS

  \(BSGS(\)\(Baby\) \(Step\) \(Gaint\) \(Step)\),大步超大步小步算法,是求高次同余方程最小正整数解的一种常用算法。通常被用于求解形如使方程 \(a^x \equiv y (mod\) \(p)\)\(p\)\(a\) )成立的最小 \(x\)

  \(BSGS\) 算法的实现过程类似数学中的缩放法,将待求的指数 \(x\) 化为 \(a \sqrt p + b\),通过枚举 \(a\) 来求解。

  具体过程如下:

    一:

    \(\large a^x \equiv y (mod\) \(\large p)\)

    \(\large a^{ k\lceil \frac x k \rceil-(k\lceil \frac x k \rceil-x)}\equiv y (mod\) \(\large p)\)  \(\large (k=\lceil \sqrt p \rceil)\)

    \(\large {(a^k)}^n*a^{-m} \equiv y (mod\) \(\large p)\)  \(\large (n=\lceil \frac x k \rceil,m=k\lceil \frac x k \rceil-x)\)

    \(\large {(a^k)}^n \equiv inv_{(a^{-m})}*y=a^{m}*y\)

    

    二:

    设 \(\large k=\lceil \sqrt p \rceil\)\(x=n*k-m\)\(n\in [1,k)\)\(m\in [1,k)\)

    则求 \(\large {(a^k)}^n \equiv inv_{(a^{-m})}*y=a^{m}*y\)

    

  于是我们便可以从前往后枚举 \(m\)\(y*(a^m)modp\) 为下标,\(m\) 为值存入一个 \(map\) 中(预处理),再枚举 \(n\) ,若存在 \(map[{(a^k)}^n]\),则 \(x=n*k-map[{(a^k)}^n]\).

  复杂度 \(O(\sqrt p log p)\)

Code:

//P3846
#include<bits/stdc++.h>
using namespace std;
int p,x,y,k,n,a;
map<int,int>M;
int qp(int x,int y){
    int s=1;
    while(y){if(y&1)s=1ll*s*x%p;x=1ll*x*x%p;y>>=1;}
    return s;
}
int main(){
    cin>>p>>a>>y;
    int k=ceil(sqrt(p));n=y;
    for(int i=0;i<k;i++){         //预处理 
        M[n]=i;
        n=1ll*n*a%p;
    }
    int t=qp(a,k);x=1;
    for(int i=1;i<=k;i++){       //枚举答案 
        x=1ll*x*t%p;
        if(M.count(x)){printf("%d\n",i*k-M[x]);return 0;}
    }
    puts("no solution");return 0;
}

猜你喜欢

转载自www.cnblogs.com/alexiswithlucifer/p/11355725.html