题意:已知a,p,b,求满足\(a^x≡b(\mod p)\)的最小的自然数x(p不一定是质数).
当p是质数的时候,我们可以直接用普通的BSGS解决.而本题中p不一定是质数,就需要用到扩展的BSGS了.
#include<bits/stdc++.h>
#define LL long long
using namespace std;
struct su{
int x,y,p;
}b[72727];
int tot,head[72727];
inline int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
inline int gcd(int a,int b){
if(b==0)return a;
return gcd(b,a%b);
}
inline int ksm(LL x,int y,int p){
int cnt=1;
while(y){
if(y&1)cnt=(cnt*x)%p;
x=(x*x)%p;y>>=1;
}
return cnt;
}
inline void hash(int x,int y){
b[++tot].x=x;b[tot].y=y;y%=72727;
b[tot].p=head[y];head[y]=tot;
}
inline int BSGS(int x,int y,int p,int ex){
int z=sqrt(p)+1;LL sx=1,sy;
for(int i=0;i<z;++i){
hash(i,sx*y%p);
sx=sx*x%p;
}
sy=sx*ex%p;//唯一的改动,这里需要乘ex
for(int i=1;i<=z;++i,sy=sy*sx%p)
for(int j=head[sy%72727];j;j=b[j].p)
if(b[j].y==sy)return i*z-b[j].x;
return -1;
}
inline int EX_BSGS(int a,int b,int p){
if(b==1)return 0;//特判b=1的情况
LL c=1,z,d;int k=0;
while(1){
d=gcd(a,p);
if(d==1)break;//a,p已经互质了就break掉
if(b%d)return -1;//d无法整除y,方程无解
++k;c=c*(a/d)%p;
//k记录除了多少次,c表示的是方程的通解
b/=d;p/=d;//利用上述同余性质
if(c==b)return k;
}
z=BSGS(a,b,p,c);
return z==-1?z:z+k;
}
int main(){
while(1){
int n=read(),mod=read(),m=read();tot=0;
if(!n&&!m&&!mod)break;
for(int i=0;i<72727;i++)head[i]=0;
//多组数据初始化
int ans=EX_BSGS(n%mod,m%mod,mod);
if(ans==-1)puts("No Solution");
else printf("%d\n",ans);
}
return 0;
}