2242: [SDOI2011]计算器
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 2077 Solved: 812
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。
Sample Output
【样例输出1】
2
1
2
【样例输出2】
2
1
0
题解:
1.快速幂。
2.扩展欧几里德。
3.BSGS,大家应该都会吧。。吾不言。
不会的可以看这里——>写的好啊!
Code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define N 100100
#define LL long long
map<LL,LL> hash;
int in(){
int x=0; char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
LL qp(LL x,LL y,LL p){
LL z=1;
while (y){
if (y&1) z=(z*x)%p;
x=(x*x)%p; y>>=1;
}
return z;
}
void work1(int y,int z,int p){
printf("%lld\n",qp(y,z,p));
}
LL gcd(LL x,LL y){
if (!y) return x;
return gcd(y,x%y);
}
void exgcd(LL a,LL b,LL &x,LL &y){
if (!b){
x=1,y=0;
return;
}
exgcd(b,a%b,x,y);
LL k=x; x=y;
y=k-a/b*y;
}
void work2(int y,int z,int p){
LL w=gcd(y,p);
if (z%w){
printf("Orz, I cannot find x!\n");
return;
}
LL x,k; exgcd(y,p,x,k);
x=x*z/w; x=(x+p)%p;
while (x<0) x+=p;
printf("%lld\n",x);
}
void work3(int y,int z,int p){
y%=p,z%=p; hash.clear();
if (!y && !z){
printf("1\n");
return;
}
if (!y){
printf("Orz, I cannot find x!\n");
return;
}
LL pp=ceil(sqrt(p)),v=qp(y,p-pp-1,p),k=1;
hash[1]=pp+1;
for (LL i=1; i<=pp; i++){
k=(k*y)%p;
if (!hash[k]) hash[k]=i;
}
LL ans=-1;
for (LL i=0; i<pp; i++){
LL j=hash[z];
if (j){
if (j==pp+1) j=0;
ans=(i*pp+j);
break;
}
z=(z*v)%p;
}
if (ans==-1) printf("Orz, I cannot find x!\n");
else printf("%lld\n",ans);
}
int main(){
int T=in(),k=in();
while (T--){
int y=in(),z=in(),p=in();
if (k==1) work1(y,z,p);
else if (k==2) work2(y,z,p);
else work3(y,z,p);
}
return 0;
}