前置知识
以及是个人都会的exgcd
Problem
洛谷P4195 【模板】exBSGS/Spoj3105 Mod
Solution
[a^xequiv bmod p\
a imes a^{x-1}equiv bmod p\
令X=a^{x-1}\
herefore a·X+p·Y=b\
exgcd求出X\
令d=gcd(a,p)\
frac ad*Xequiv frac bdmod frac pd\
Xequivfrac bd*frac damod frac pd\
a^{x-1}equivfrac bamod 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
",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
*/