【文文殿下】ExBSGS

无需逆元版本:

#include<cstdio>
#include<cassert>
#include<cmath>
#include<map>
typedef long long ll;
ll gcd(ll a,ll b) {
    return b?gcd(b,a%b):a;
}
ll qpow(ll a,ll b,ll p) {
    ll ret = 1;
    while(b) {
        if(b&1) {
            ret=ret*a%p;
        }
        a=a*a%p;
        b>>=1;
    }
    return ret;
}
ll exgcd(ll a,ll b,ll &x,ll &y) {
    if(b==0) {
        x=1;y=0;
        return a;
    }
    ll d = exgcd(b,a%b,x,y);
    ll tmp = x;
    x = y;
    y=tmp-a/b*y;
    return d;
}
inline ll bsgs(ll a,ll b,ll p) {
    std::map<ll,ll> M;
    if(p==1) return 0;
    a%=p;b%=p;
    ll d,cnt=0,q=1;
    while((d=gcd(a,p))!=1) {
        if(b==1) return cnt;
        if(b%d) return -1;
        b/=d;
        p/=d;
        ++cnt;
        q=a/d*q%p;
    }
    ll lmt = ceil(sqrt(p));
    ll tmp = b%p;
    for(int i = 0;i<lmt;++i,tmp=tmp*a%p) {
        M[tmp]=i;
    }
    tmp = qpow(a,lmt,p);
    for(int i = 1;i<=lmt+1;++i) {
        q=q*tmp%p;
        if(M.count(q)) {
            return i*lmt-M[q]+cnt;
        }
    }
    return -1;
}
int main() {
    ll a,b,p;
    scanf("%lld%lld%lld",&a,&p,&b);
    while(a||b||p) {
        ll ans = bsgs(a,b,p);
        if(ans==-1) puts("No Solution");
        else printf("%lld\n",ans);
        scanf("%lld%lld%lld",&a,&p,&b);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Syameimaru/p/10221311.html
今日推荐