说是BSGS……但是跟前面那题的扩展BSGS其实是一样的……因为模数虽然是质数,但是其可能可以整除a!!所以这两者其实是一样的……
第一二种操作不赘述。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; ll Quick_Pow(ll a,ll p,ll MOD){ if(!p){ return 1; } ll ans=Quick_Pow(a,p>>1,MOD); ans=ans*ans%MOD; if((p&1)==1){ ans=(a%MOD*ans)%MOD; } return ans; } void exgcd(ll a,ll b,ll &d,ll &x,ll &y){ if(!b){ d=a; x=1; y=0; } else{ exgcd(b,a%b,d,y,x); y-=x*(a/b); } } #define MAXN 100001 #define MOD 100003 struct HashTable { ll v[MAXN]; int __next[MAXN],first[MOD],en,a[MAXN]; void Insert(ll x,int J){ if(Find(x)!=-1){ return; } int o=x%MOD; v[en]=x; a[en]=J; __next[en]=first[o]; first[o]=en++; } int Find(ll x){ int o=x%MOD; for(int i=first[o];i!=-1;i=__next[i]){ if(v[i]==x){ return a[i]; } } return -1; } void Clear(){ memset(first,-1,sizeof(first)); en=0; } }T; ll a,b,p; int zu,op; int main(){ // freopen("d.in","r",stdin); scanf("%d%d",&zu,&op); for(;zu;--zu){ scanf("%lld%lld%lld",&a,&b,&p); if(op==3){ T.Clear(); b%=p; ll tmp,D=1; int cnt=0; bool flag=0; while((tmp=__gcd(a,p))!=1){ if(b%tmp){ puts("Orz, I cannot find x!"); flag=1; break; } ++cnt; p/=tmp; b/=tmp; D=D*a/tmp%p; } if(flag){ continue; } int m=ceil(sqrt(p)); ll aj=1; T.Insert(aj,0); for(int j=1;j<=m;++j){ aj=(a%p*aj)%p; T.Insert(aj,j); } for(int i=0;i<=m;++i){ ll x,y,d; exgcd(D,p,d,x,y); x=x*(b/d); x=(x%(p/d)+p/d)%(p/d); int J; if((J=T.Find(x))!=-1){ printf("%lld ",(ll)i*(ll)m+(ll)J); flag=1; break; } D=(D*aj)%p; } if(!flag){ puts("Orz, I cannot find x!"); } } else if(op==1){ printf("%lld ",Quick_Pow(a,b,p)); } else{ ll d,x,y; exgcd(a,p,d,x,y); if(b%d){ puts("Orz, I cannot find x!"); continue; } x=x*(b/d); x=(x%(p/d)+p/d)%(p/d); printf("%lld ",x); } } return 0; }