题解 P2485 【[SDOI2011]计算器】
其实这道题真心不难,主要也就是BSGS
题目里面有限制条件: p 为质数
你以为它很有用么?a 可以是 p 的倍数啊,这样两数就不互质了
你以为它没用么?a 是 p 的倍数特判掉就好了啊都不带运算的
第一问其实就是 快速幂
第二问其实就是 求逆元(费马小定理)
第三问其实就是 BSGS
//by Judge
#include<map>
#include<cmath>
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
const int M=1e5+7;
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){ int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} ll n,k,y,z,mod; map<ll,int> mp;
inline ll qpow(ll x,ll p){ ll s=1;
for(;p;p>>=1,x=x*x%mod)
if(p&1) s=s*x%mod; return s;
}
inline ll BSGS(ll a,ll b){
if(!(a%mod)&&b) return 0; // a 是 mod 的倍数,除非 b 等于 0 否则无解
mp.clear();
ll h=b%mod,s=sqrt(mod)+1;
ll t=qpow(a,mod-2);
for(int i=0;i<=s;++i){
if(!mp.count(h)) mp[h]=i;
h=h*t%mod;
} h=1,t=qpow(a,s);
for(int i=0;i<=s;++i){
if(mp.count(h)) return printf("%lld\n",mp[h]+s*i),1;
h=h*t%mod;
} return 0;
}
int main(){ n=read(),k=read();
if(k==1){ for(;n;--n)
y=read(),z=read(),mod=read(),
printf("%lld\n",qpow(y,z));
} else if(k==2){ for(;n;--n){
y=read(),z=read(),mod=read();
if(!(y%mod)&&z) puts("Orz, I cannot find x!"); // y 是 mod 的倍数,除非 z=0 否则无解
else y=qpow(y,mod-2),z=y*z%mod,printf("%lld\n",z);
}
} else{ for(;n;--n){
y=read(),z=read(),mod=read();
if(!BSGS(y,z)) puts("Orz, I cannot find x!");
}
} return 0;
}