函数
- long long exBSGS(long long a,long long b,long long P):求满足 ax≡b(modp) 的最小自然数 x,a,p 不一定互质。
代码
long long qmi(long long a,long long b,long long c){
long long ans=1;
while(b){
if(b&1)
ans=ans*a%c;
a=a*a%c;
b>>=1;
}
return ans;
}
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){
x=1;y=0;
return a;
}
ll d=exgcd(b,a%b,x,y);
ll z=x;x=y;y=z-a/b*x;
return d;
}
map<int,int>ahash;
int Baby_Step_Giant_Step(int a,int b,int p){
ahash.clear();
b%=p;
int t=(int)sqrt(p)+1,val=b;
for(int j=0;j<t;j++){
if(j)
val=1ll*val*a%p;
ahash[val]=j;
}
a=qmi(a,t,p);
if(!a)
return b?-1:1;
for(long long i=0;i<=t;i++){
val=qmi(a,i,p);
int j=ahash.find(val)==ahash.end()?-1:ahash[val];;
if(j>=0&&i*t-j>=0)
return i*t-j;
}
return -1;
}
ll exBSGS(ll a,ll b,ll p){
a%=p;b%=p;
if(b==1||p==1)
return 0;
ll cnt=0,s=1,t=1;
for(ll i=0;i<=50;i++){
if(t==b)
return i;
t=t*a%p;
}
bool f=0;
while(1){
ll d=gcd(a,p);
if(d==1)
break;
if(b%d){
return -1;
}
cnt++;
b/=d;p/=d;
s=s*(a/d)%p;
}
ll x,y;
exgcd(s,p,x,y);
b=b*(x%p+p)%p;
ll ans=Baby_Step_Giant_Step(a,b,p);
if(ans==-1)
return ans;
return ans+cnt;
}