【题目描述】
你被要求设计一个计算器完成以下三项任务:
1、给定y、z、p,计算y^z mod p 的值;
2、给定y、z、p,计算满足xy ≡z(mod p)的最小非负整数x;
3、给定y、z、p,计算满足y^x ≡z(mod p)的最小非负整数x。
为了拿到奖品,全力以赴吧!
【输入格式】
输入文件calc.in包含多组数据。
第一行包含两个正整数T、K,分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
以下T 行每行包含三个正整数y、z、p,描述一个询问。
【输出格式】
输出文件calc.out 包括T 行.
对于每个询问,输出一行答案。
对于询问类型2 和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”。
S a m p l e I n p u t Sample~~Input Sample Input
4 3
2 1 3
2 2 3
2 3 3
2 4 3
S a m p l e O u t p u t Sample~~Output Sample Output
0
1
Orz, I cannot find x!
0
【题意分析】
对于1, 快速幂即可
对于2,球逆元,费马小定理即可,但我用了exgcd
对于3,套bsgs即可
但是别忘了bsgs有一种情况无解(显而易见却容易忽略)
方程
a x ≡ b ( m o d p ) a^x\equiv b(mod~~p) ax≡b(mod p)
其中p为质数,当 p ∣ a p|a p∣a且 b b b不等于0时无解
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <map>
#include <algorithm>
#define int long long
using namespace std;
int n, opt, a, b, qy, x, y;
inline int pow (int a, int b) {
if (! b) return 1; if (b == 1) return a;
int base = 1;
while (b) {
if (b & 1) base = base * a % qy;
a = a * a % qy; b >>= 1;
}
return base;
}
int GCD (int a, int b) {
if (! b) return a;
return GCD (b, a % b);
}
void EXGCD (int a, int b, int &x, int &y) {
if (! b) {
x = 1, y = 0; return;
}
EXGCD (b, a % b, x, y);
int tmp = x;
x = y, y = tmp - a / b * y;
}
inline int BSGS (int a, int b) {
map <int, int> hash;
if (! (a % qy) && b) return -1;
int lim = ceil (sqrt (qy)), base = b % qy;
for (register int i = 1; i <= lim; i++)
base = base * a % qy, hash[base] = i;
base = pow (a, lim);
int o = 1;
for (register int i = 1; i <= lim; i++) {
o = o * base % qy;
if (hash[o]) return ((i * lim - hash[o]) % qy + qy) % qy;
}
return -1;
}
signed main () {
scanf ("%lld%lld", &n, &opt);
for (register int i = 1; i <= n; i++) {
scanf ("%lld%lld%lld", &a, &b, &qy);
if (opt == 1) printf ("%lld\n", pow (a, b));
if (opt == 2) {
int gcd = GCD (a, qy); x = y = 0;
if (b % gcd) puts ("Orz, I cannot find x!");
else EXGCD (a, qy, x, y), x *= b,
x = (x % qy + qy) % qy, printf ("%lld\n", x);
}
if (opt == 3) {
int ans = BSGS (a, b);
if (ans == -1) puts ("Orz, I cannot find x!");
else printf ("%lld\n", ans);
}
}
return 0;
}