已知数a,p,b,求满足a^x≡b(mod p)的最小自然数x。
EXBSGS版子
#include<queue>
#include<cmath>
#include<cctype>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=350000;
int a,p,b,ans;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int ret=exgcd(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-a/b*y;
return ret;
}
int niyuan(int a,int p)
{
int x,y;
int d=exgcd(a,p,x,y);
if(d!=1)return -1;
return (x+p)%p;
}
int qkpow(int a,int p,int mod)
{
LL t=1,tt=a%mod;
while(p)
{
if(p&1)t=t*tt%mod;
tt=tt*tt%mod;
p>>=1;
}
return t;
}
struct data
{
int id,d;
friend bool operator<(data a,data b)
{
return a.d!=b.d?a.d<b.d:a.id<b.id;
}
}BG[maxn];
int BGSG(int a,int b,int p)
{
int m=ceil(sqrt(p)),t;
t=1%p;
for(int j=0;j<m;j++,t=1ll*t*a%p)
BG[j]=(data){j,t};
sort(BG,BG+m);
t=1%p;
int tt=qkpow(a,m,p),f,s;
for(int i=0;i<=m;i++,t=1ll*t*tt%p)
{
f=1ll*b*niyuan(t,p)%p;
s=lower_bound(BG,BG+m,(data){0,f})-BG;
if(BG[s].d==f)
return i*m+BG[s].id;
}
return -1;
}
int exBGSG(int a,int b,int p)
{
a%=p,b%=p;//细节
int cnt=0,v=1;
if(b==1)return 0;//细节
for(int d=gcd(a,p);d!=1;d=gcd(a,p))
{
if(b%d)return -1;
b/=d,p/=d;v=1ll*v*a/d%p;//v还可以这么mod感觉很棒,因为最后的p是当前p的因数,所以应该是成立的
cnt++;
if(b==v)return cnt;//细节
}
int tmp=BGSG(a%p,1ll*b*niyuan(v,p)%p,p);//v和p0明显是互质的,因为v只包含a的因数,但是p0和a互质
if(tmp==-1)return tmp;
return tmp+cnt;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
while(~scanf("%d%d%d",&a,&p,&b) && (a || b || p))
{
ans=exBGSG(a,b,p);
if(ans==-1)
printf("No Solution\n");
else
printf("%d\n",ans);
}
return 0;
}