BZOJ 2242
2242: [SDOI2011]计算器
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 5142 Solved: 1964
[Submit][Status][Discuss]
Description
你被要求设计一个计算器完成以下三项任务:
1、给定y,z,p,计算Y^Z Mod P 的值;
2、给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数;
3、给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数。
Input
输入包含多组数据。
第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
以下行每行包含三个正整数y,z,p,描述一个询问。
Output
对于每个询问,输出一行答案。对于询问类型2和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。
Sample Input
【样例输入1】
3 1
2 1 3
2 2 3
2 3 3
【样例输入2】
3 2
2 1 3
2 2 3
2 3 3
【数据规模和约定】
对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。
3 1
2 1 3
2 2 3
2 3 3
【样例输入2】
3 2
2 1 3
2 2 3
2 3 3
【数据规模和约定】
对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。
Sample Output
【样例输出1】
2
1
2
【样例输出2】
2
1
0
2
1
2
【样例输出2】
2
1
0
HINT
Source
此题做法多种多样(我指的是第二问hhh)
1:quickpow ; 3:bsgs 无疑问
2:可以用exgcd,也可以直接用一下逆元,毕竟p是素数。
为了复习exgcd,我决定用比较烦的exgcd做
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<complex> #include<map> #include<cstring> #define ll long long using namespace std; ll read() { ll x=0,f=1;char s=getchar(); while(s<'0' || s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0' && s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } ll y,z,p; ll pow(ll a,ll x) { ll ans=1; for(;x>0;x>>=1,a=a*a%p) if(x&1)ans=ans*a%p; return ans%p; } ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0){x=1;y=0;return a;} ll q=exgcd(b,a%b,y,x);y-=(a/b)*x; return q; } ll T,K; map<ll,ll>m; void bsgs(ll a,ll b,ll p) { m.clear(); if(a%p==0 && b%p==0){printf("0\n");return;} if(a%p==0 && b%p!=0){printf("Orz, I cannot find x!\n");return;} ll x=b%p,s=ceil(sqrt(p));m[x]=0; //printf("%lld %lld\n",s,x); for(int i=1;i<=s;i++){x=(x*a)%p;m[x]=i;/*printf("%d %lld\n",i,x);*/} ll t=pow(a,s);x=1; for(int i=1;i<=s;i++) { x=(x*t)%p; //printf("%lld ",x); if(m[x]) { ll ans=i*s-m[x]; printf("%lld\n",(ans%p+p)%p); return; } } printf("Orz, I cannot find x!\n"); } int main() { T=read(),K=read(); while(T--) { y=read(),z=read(),p=read(); if(K==1)printf("%lld\n",pow(y,z)); if(K==2) { ll a,b,d; d=exgcd(y,p,a,b); if(z%d!=0)printf("Orz, I cannot find x!\n"); else { ll ans=(z/d)*a,mod=p/d; ans=(ans%mod+mod)%mod; printf("%lld\n",ans%p); } } if(K==3)bsgs(y,z,p); } return 0; }
噢对了,小心特判!!