# bzoj2242 [SDOI2011]计算器——BSGS

BSGS意外地挺好写的！

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<cmath>
using namespace std;
typedef long long ll;
map<ll,int>mp;
ll T,x,y,Y,Z,P,tp;
ll pw(ll a,ll b,ll mod)
{
ll ret=1;
for(;b;b>>=1ll,a=(a*a)%mod)
if(b&1)ret=(ret*a)%mod;
return ret;
}
ll gcd(ll a,ll b){return a%b?gcd(b,a%b):b;}
ll BSGS()
{
mp.clear();
if(Y%P==0)return -1;
ll m=ceil(sqrt(P));
ll tmp=Z;//tmp=1
for(int j=0;j<=m;j++)//1
{
if(!j){mp[tmp]=j; continue;}
tmp=(tmp*Y)%P;
mp[tmp]=j;
}
//    tmp=pw((pw(Y,m,P)),P-2,P); ll nw=Z%P;
tmp=pw(Y,m,P); ll nw=tmp;//
for(int i=1;i<=m;i++)//0
{
if(mp[nw])return (i*m%P-mp[nw]%P+P)%P;//i*m+mp[nw]
nw=(nw*tmp)%P;
}
return -1;
}
void exgcd(ll a,ll b,ll &x,ll &y){
if(!b){x=1,y=0;return;}
exgcd(b,a%b,x,y);
ll t=x;x=y;y=t-a/b*y;
}
int main()
{
scanf("%lld%lld",&T,&tp);
while(T--)
{
scanf("%lld%lld%lld",&Y,&Z,&P);
if(tp==1){printf("%lld\n",pw(Y,Z,P));}
if(tp==2)
{
ll g=gcd(Y,P);
if(Z%g){printf("Orz, I cannot find x!\n");continue;}
Y/=g; P/=g; Z/=g;
exgcd(Y,P,x,y);
printf("%lld\n",(x*Z%P+P)%P);//*Z 而非 *g !!!
}
if(tp==3)
{
ll ans=BSGS();
if(ans==-1)printf("Orz, I cannot find x!\n");
else printf("%lld\n",ans);
}
}
return 0;
}

posted @ 2018-07-05 20:14  Zinn  阅读(152)  评论(0编辑  收藏  举报