第一问快速幂,第二问扩欧,第三问BSBG,注意特判。。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
map<int,int> mp;
int T,i,k;
ll y,z,p,ans;
ll pow(ll a,ll t,ll p)
{
if (t==0) return 1ll;
ll b=pow(a,t/2,p);
b=(b*b)%p;
if (t%2) b=(b*a)%p;
return b;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if (b==0) {x=1;y=0;return a;}
ll x1,y1,d=exgcd(b,a%b,x1,y1);
x=y1;y=x1-(a/b)*y1;
return d;
}
void solve2(ll y,ll z,ll p)
{
ll x,c,d=exgcd(y,p,x,c);
if (z%d) {printf("Orz, I cannot find x!\n");return;}
y/=d;z/=d;p/=d;
x=(x*z)%p;
if (x<0) x=(x+(-x/p+1)*p)%p;
printf("%lld\n",x);
}
ll bsgs(ll a,ll b,ll p) //a^x≡b(mod p)
{
a%=p;
if (b==1) return 0;
if (!a&&!b)return 1;
if (!a) return -1;
int m=ceil(sqrt(p*1.0)),i;
ll w=1;
mp.clear();
mp[1]=2*m;
for (i=1;i<m;i++) {w=(w*a)%p;if (!mp[w]) mp[w]=i;}
ll t=pow(a,p-m-1,p);w=1;
for (i=0;i<m;i++)
{
int j=mp[(w*b)%p];
if (j) return (ll)i*m+j%m;
else w=(w*t)%p;
}
return -1;
}
int main()
{
freopen("2242.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d%d",&T,&k);
while (T--)
{
scanf("%lld%lld%lld",&y,&z,&p);
switch(k)
{
case(1):printf("%lld\n",pow(y,z,p));break;
case(2):solve2(y,z,p);break;
case(3):
ans=bsgs(y,z,p);
if (ans==-1) printf("Orz, I cannot find x!\n");else printf("%lld\n",ans);
break;
}
}
}