ghy
题解:
注:BSGS和扩展欧几里德的应用条件都是是A,P互质,那么这道题出来下面写出的麻烦的方法,还可以直接求
A^x-k=B*inv(A^k) (mod p') ,inv(A^k) 用扩展欧几里德来求。
<span style="font-size:18px;">#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define ll long long #define q 100003 using namespace std; ll a,b,p,cnt,tot; ll point[q<<1],v[q<<1],u[q<<1],next[q<<1]; void add(ll x,ll y) { ll k=x%q; tot++; next[tot]=point[k]; u[tot]=x; v[tot]=y; point[k]=tot; } ll find(int x)//hash { ll k=x%q; for (ll i=point[k];i;i=next[i]) if (u[i]==x) return v[i]; return -1; } ll quickpow(ll num,ll x,ll m)//快速幂 { ll ans=1; ll base=num%m; while (x) { if (x&1) ans=ans*base%m; x>>=1; base=base*base%m; } return ans%m; } ll gcd(ll x,ll y)//最大公约数 { ll r; while (y) { r=x%y; x=y; y=r; } return x; } ll exbsgs(ll a,ll b,ll p) { a%=p; b%=p; if (b==1) return 0; ll cnt=0,d=1,tmp=1; while((tmp=gcd(a,p))!=1)//不断除以a,p的最大公约数,直到a,p互质 { if (b%tmp) return -1; b/=tmp; p/=tmp; cnt++; d=d*(a/tmp)%p;//记录的是A^x-cnt的系数 if (b==d) return cnt; } ll m=ceil(sqrt(p)); ll ans=b; ll sum=1; tot=0; memset(point,0,sizeof(point)); memset(next,0,sizeof(next)); tmp=quickpow(a,m,p); add(ans,0); for (ll i=1;i<=m;i++) ans=ans*a%p,add(ans,i); for (ll i=1;i<=m+1;i++) { d=d*tmp%p; ll t=find(d); if (t!=-1) return i*m-t+cnt; } return -1; } int main() { freopen("input.txt","r",stdin); freopen("my.out","w",stdout); while (scanf("%I64d%I64d%I64d",&a,&p,&b)) { if (a==0&&b==0&&p==0) break; ll t=exbsgs(a,b,p); if (t!=-1) printf("%I64d\n",t); else printf("No Solution\n"); } }</span>