exBSGS学习笔记

前置知识

大步小步定理

以及是个人都会的exgcd

Problem

洛谷P4195 【模板】exBSGS/Spoj3105 Mod

Solution

\[ a^x\equiv b\mod p\\ a\times a^{x-1}\equiv b\mod p\\ 令X=a^{x-1}\\ \therefore a·X+p·Y=b\\ exgcd求出X\\ 令d=gcd(a,p)\\ \frac ad*X\equiv \frac bd\mod \frac pd\\ X\equiv\frac bd*\frac da\mod \frac pd\\ a^{x-1}\equiv\frac ba\mod \frac pd\\ \]

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
struct Hashmap{
    static const int MAXINT=((1<<30)-1)*2+1,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];
    }
}hs;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int exgcd(int a,int b,int &x,int &y){
    if(!b){return x=1,y=0,a;}
    int re=exgcd(b,a%b,x,y),t=x;
    x=y;y=t-a/b*y;
    return re;
}
int fk(int a,int b,int p){
    if(p==1)return 0;
    if(b==1)return a?0:-1;
    if(a%p==0)return b?-1:1;
    int Gcd,d=1,add=0;
    while((Gcd=gcd(a,p))>1){
        if(b%Gcd)return -1;
        b/=Gcd,p/=Gcd,d=(d*a/Gcd)%p;
        add++;
    }
    for(int i=0,fkk=1;i<add;i++,fkk=(fkk*a)%p)
        if(fkk==b)return i;
    int m=sqrt(p),bs=1;hs.clear();
    for(int i=0;i<m;i++){
        hs[bs]=min(hs[bs],i);
        bs=(bs*a)%p;
    }
    for(int i=0;i<m;i++){
        int x,y;
        Gcd=exgcd(d,p,x,y);
        x=(x*b%p+p)%p;
        if(hs.count(x))return i*m+hs[x]+add;
        d=(d*bs)%p;
    }
    return -1;
}
signed main(){
    int a,b,p,ans;
    while(1){
        scanf("%lld%lld%lld",&a,&p,&b);
        if(p==0)break;
        ans=fk(a,b,p);
        if(ans==-1)puts("No Solution");
        else printf("%lld\n",ans);
    }
    return 0;
}
/*
5 58 33
2 4 3
2 5 1
2 5 2
2 5 3
2 5 4
3 5 1
3 5 2
3 5 3
3 5 4
4 5 1
4 5 2
4 5 3
4 5 4
2 12345701 1111111
65537 1111111121 1111111111
0 0 0

*/
posted @ 2019-05-17 09:52 The_KOG 阅读(...) 评论(...) 编辑 收藏