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
*/