【笔记】BSGS算法

参考资料

(OI-WIKI)[https://oi-wiki.org/math/bsgs/]

(Miskcoo)[http://blog.miskcoo.com/2015/05/discrete-logarithm-problem]

BSGS算法流程

给定a,b,p, 求解 

复杂度O(√p)

具体看Miskcoo的教程

代码

#include<bits/stdc++.h>
typedef long long ll;
const int MOD=76543;
int flag;
ll hs[MOD],head[MOD],next[MOD],id[MOD],top;
ll inv(ll x,ll p,ll mod){
    ll v=1;
    while(p){
    if(p&1)v=x*v%mod;
    x=x*x%mod;
    p>>=1;
    }
    return v;
}
void insert(ll x,int y){
    ll k=x%MOD;
    hs[++top]=x,id[top]=y,next[top]=head[k],head[k]=top;
}
ll find(int x){
    ll k=x%MOD;
    for(int i=head[k];i!=0;i=next[i])
    if(hs[i]==x)return id[i];
    return -1;
}
ll bsgs(ll a,ll p,ll b) {
    memset(head,0,sizeof(head)),top=0;
    a%=p,b%=p;
    if(b==1)return 0;
    ll cnt=0;
    ll t=1;
    for(ll g=std::__gcd(a,p);g!=1;g=std::__gcd(a,p)){
    if(b%g)return -1;
    p=p/g;
    b=b/g;
    t=t*a/g%p;
    if(b==t)return 0;
    cnt++;
    }
    ll m=ceil(sqrt(p*1.0));
    ll x=t,a_B=1;
    for(ll i=0;i<m;i++,a_B=a_B*a%p)insert(b*a_B%p,i);
    a_B=inv(a,m,p);
    for(ll A=m;;A+=m){
    x=x*a_B%p;
    int j=find(x);
    if(j!=-1)return A-j+cnt;
    if(A>p)break;
    }
    return -1;
}
int main() {
    ll a,p,b;
    while(scanf("%lld%lld%lld",&a,&p,&b)!=EOF&&(a|b|p)) {
    if(p==1) {puts("0");continue;}
    flag=0;
    ll x=bsgs(a,p,b);
    if(x==-1)puts("No Solution");
    else
    printf("%lld\n",x);
    }
}

猜你喜欢

转载自www.cnblogs.com/greenty1208/p/9720681.html