该算法是用来解决A^x=B(mod C)这一类问题的。
BSGS算法只能适用于C为素数的情况。
m=sqrt(C);
x=m*i+j;
A^x=A^(i*m)*A^j;
每次枚举i,令D=A^(i*m);
D*A^j=B(mod C);
D*A^j+C*y=B;
用扩展欧几里得可以求出A^j
通过hash查出对应的j;
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long
const int sqr=50007;
bool hash[sqr+10];
LL val[sqr+10],j[sqr+10],A,B,C;
void insert(LL jj,LL vv)
{
int v=vv%sqr;
while(hash[v]&&val[v]!=vv)
{
v++;
if(v==sqr)
v-=sqr;
}
hash[v]=1;
j[v]=jj;
val[v]=vv;
}
int found(LL vv)
{
int v=vv%sqr;
while(hash[v]&&val[v]!=vv)
{
v++;
if(v==sqr)
v-=sqr;
}
if(hash[v]==0)
return -1;
return j[v];
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x=1;y=0;
return a;
}
LL ret=exgcd(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-(a/b)*y;
return ret;
}
LL baby_step(LL A,LL B,LL C)
{
for(int i=0;i<sqr+10;i++)
hash[i]=0,j[i]=0,val[i]=0;
int m=ceil(sqrt(C*1.0));
LL D=1,res=1,x=0,y=0;
for(int i=0;i<m;i++)
{
insert(i,D);
D=D*A%C;
}
for(int i=0;i<m;i++)
{
exgcd(res,C,x,y);
int j=found(x);
if(j!=-1)
return LL(i*m+j);
res=res*D%C;
}
return -1;
}
int main()
{
scanf("%d %d %d",&A,&B,&C);
LL x=baby_step(A,B,C);
if(x==-1)
cout<<"NO"<<endl;
else
cout<<x<<endl;
return 0;
}