Submit: 4336 Solved: 1672
[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
第一问快速幂
第二问exgcd
第三问BSGS,好麻烦我就先略
为啥叫baby step giant step,我其实不是很懂
求(y^x = z(mod~p))设(x=km+i)[y^{km}*y^iequiv z](y^iequiv z*ine(y^{km}))(逆元)
用费马小定理显然可得(ine(y^m)equiv y^{p-1-m})设其为T
[ine(y^{km})equiv ine(y^{(k-1)m})*T]
把[y^i(0<=i<=m)]放入hash或者map
然后枚举k,查询[z*ine(y^{km})]
显然m取(sqrt p)复杂度比较优秀。。
解释部分转自黄学长
#include <ctype.h> #include <cstdio> #include <cmath> #include <map> using namespace std; typedef long long LL; map<LL,int>q; void read(int &x) { x=0;bool f=0; register char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=1; for(; isdigit(ch);ch=getchar()) x=x*10+ch-'0'; x=f?(~x)+1:x; } inline LL ksm(int a,int b,int c) { LL base=a,r=1%c; while(b) { if(b&1) r=(r*base)%c; base=(base*base)%c; b>>=1; } return r; } int gcd(int a,int b) {return a%b==0?b:gcd(b,a%b);} void exgcd(int a,int b,int &x,int &y) { if(b==0) { x=1;y=0; return; } exgcd(b,a%b,x,y); int tmp=x; x=y; y=tmp-(a/b)*y; } int T,L; int main() { read(T); read(L); for(int y,z,p;T--;) { read(y); read(z); read(p); switch(L) { case 1: { printf("%d ",ksm(y,z,p)); break; } case 2: { int m,n; p=-p; int k=gcd(y,p); if(z%k) printf("Orz, I cannot find x! "); else { y/=k;z/=k;p/=k; exgcd(y,p,m,n); m=(LL)m*z%p; for(;m<0;m+=p); printf("%d ",m); } break; } case 3: { if(y%p==0&&z==0) printf("1 "); else if(y%p==0) printf("Orz, I cannot find x! "); else { q.clear(); bool flag=false; LL t=1,m=ceil(sqrt(p)); q[1]=m+1; for(LL i=1;i<m;i++) { t=t*y%p; if(!q[t]) q[t]=i; } t=ksm(y,p-m-1,p);LL in=1; for(LL k=0;k<m;k++) { int ans=z*in%p; if(q[ans]) { int v=q[ans]; if(v==m+1) v=0; printf("%lld ",k*m+v); flag=true; break; } in=in*t%p; } if(!flag) printf("Orz, I cannot find x! "); } break; } } } return 0; }