扩展BSGS求解离散对数问题

扩展BSGS用于求解axΞb mod(n) 同余方程中gcd(a,n)≠1的情况

基本思路,将原方程转化为a与n互质的情况后再套用普通的BSGS求解即可

struct Hashmap{
    static const int Ha=999917,maxe=46340;
    int E,lnk[Ha],son[maxe+5],nxt[maxe+5],w[maxe+5];
    int top,stk[maxe+5];
    void clear() {E=0;while(top) lnk[stk[top--]]=0;}
    void Add(int x,int y){son[++E]=y;nxt[E]=lnk[x];w[E]=maxint;lnk[x]=E;}
    bool count(int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return true;
        return false;
    }
    int& operator [] (int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return w[j];
        Add(x,y);stk[++top]=x;return w[E];
    }
};
Hashmap f;
int gcd(int a,int b){
    if(!b) return a;
    else return gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y)
{
    if(!b) {x=1;y=0;return a;}
    int r=exgcd(b,a%b,x,y),t=x;
    x=y;y=t-(a/b)*y;
    return r;
}

int exBSGS(int A,int B,int C)
{
    if(C==1) if(!B) return A!=1;else return -1;
    if(B==1) if(A) return 0;else return -1;
    if(A%C==0) if(!B) return 1;else return -1;
    int r,D=1,num=0;
    while((r=gcd(A,C))>1)
    {
        if(B%r) return -1;num++;
        B/=r;C/=r;D=((ll)D*A/r)%C;
    }
    for(int i=0,now=1;i<num;i++,now=((ll)now*A)%C)
    {
        if(now==B) return i;
    }
    int m=ceil(sqrt(C)),Base=1;f.clear();
    for(int i=0;i<=m-1;i++)
    {
        f[Base]=min(f[Base],i);
        Base=((ll)Base*A)%C;
    }
    for(int i=0;i<=m-1;i++)
    {
        int x,y,r=exgcd(D,C,x,y);
        x=((ll)x*B%C+C)%C;
        if(f.count(x)) return i*m+f[x]+num;
        D=((ll)D*Base)%C;
    }
    return -1;
}

猜你喜欢

转载自www.cnblogs.com/033000-/p/10087321.html