1. 程式人生 > >擴充套件BSGS求解離散對數問題

擴充套件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; }