2242: [SDOI2011]计算器
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3045 Solved: 1206
[ 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
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int hash = 999983;
typedef long long LL;
int T,typ,top,s[hash],ha[hash],va[hash];
int ksm(LL x,int y,LL p)
{
LL ret = 1;
for (; y; y >>= 1) {
if (y & 1) ret = ret*x%p;
x = x*x%p;
}
return ret;
}
LL gcd(LL a,LL b,LL &x,LL &y)
{
if (!b) {
x = 1; y = 0;
return a;
}
LL ret = gcd(b,a%b,x,y);
LL tmp = x;
x = y;
y = tmp - y*(a/b);
return ret;
}
LL GCD(LL a,LL b,LL z)
{
LL x,y;
LL g = gcd(a,b,x,y);
if (z % g != 0) return -1;
x = x * z / g;
if (x < 0)
x = x % b + b;
return x % b;
}
void hash_insert(int v,int mi)
{
int posi = v%hash;
while (va[posi] != -1) {
if (va[posi] == v) return;
++posi;
}
va[posi] = v; ha[posi] = mi;
s[++top] = posi;
}
int hash_search(LL now)
{
int posi = now%hash;
for (;;) {
if (va[posi] == -1) return -1;
if (va[posi] == now) return ha[posi];
++posi;
}
}
LL Baby_step(LL t,LL p,LL z,LL Sqrt)
{
LL now = 1;
for (int i = 0; i <= Sqrt; i++) {
LL x = GCD(now,p,z);
if (x == -1) continue;
int posi = hash_search(x%p);
if (posi != -1)
return i*Sqrt + posi;
now = now*t%p;
}
return -1;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
memset(va,-1,sizeof(va));
cin >> T >> typ;
while (T--) {
if (typ == 1) {
int x,y,p;
cin >> x >> y >> p;
printf("%d\n",ksm(x,y,p));
}
else if (typ == 2) {
int y,z,p; LL x;
cin >> y >> z >> p;
x = GCD(y,p,z);
if (x == -1) puts("Orz, I cannot find x!");
else cout << x << endl;
}
else {
int y,z,p,Sqrt,t; LL x;
cin >> y >> z >> p;
Sqrt = sqrt(p);
if (Sqrt * Sqrt < p) ++Sqrt;
int now = 1; //top = 0;
for (int i = 0; i <= Sqrt; i++)
hash_insert(now,i),now = 1LL*now*y%p;
t = ksm(y,Sqrt,p);
x = Baby_step(t,p,z,Sqrt);
if (x == -1) puts("Orz, I cannot find x!");
else cout << x << endl;
while (top) va[s[top--]] = -1;
}
}
return 0;
}