你被要求设计一个计算器完成以下三项任务:
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。
为了拿到奖品,全力以赴吧!
思路:
对于询问1,快速幂解决
对于询问2,扩展欧几里得解决
对于询问3,采用BSGS算法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll p, a, b;
ll qmul(ll a, ll b, ll mod) {
ll ans = 0;
while (b) {
if (b & 1) {
ans = (ans + a) % mod;
}
a = (a + a) % mod;
b >>= 1;
}
return ans % mod;
}
ll qpow(ll a, ll b, ll mod) {
ll ans = 1;
while (b) {
if (b & 1) {
ans = (ans * a) % mod;
}
a = (a * a) % mod;
b >>= 1;
}
return ans % mod;
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1; y = 0;
return a;
} else {
ll d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
}
ll bsgs(ll a, ll b, ll p) {
b%=p;a%=p;
ll n = sqrt(p) + 1;
map<ll,ll> mp;
mp.clear();
ll ans = b%p;
if (a == 0 && b == 0) return 0;
if (a == 0 && b != 0) return -1;
for (int i = 0; i <= n; i++) {
mp[ans] = i;
ans = qmul(ans, a, p);
}
ans = 1;
for (int i = 1; i <= n; i++) ans = qmul(ans, a, p);
ll ret = 1;
for (int i = 1; i <= n; i++) {
ret = qmul(ret, ans, p);
if (mp[ret] != 0) {
return (ll)i * n - mp[ret];
}
}
return -1;
}
int main() {
int n, opt;
ll a, b, p, x, y;
while (scanf("%d%d", &n, &opt) != EOF) {
for (int i = 1; i <= n; i++) {
scanf("%lld%lld%lld", &a, &b, &p);
if (opt == 1) {
printf("%lld\n", qpow(a, b, p));
} else if (opt == 2) {
ll d = exgcd(a, p, x, y);
if (b % d != 0) {
printf("Orz, I cannot find x!\n");
} else {
x = qpow(a, p - 2, p) * b % p;
printf("%lld\n", x);
}
} else {
ll ans = bsgs(a, b, p);
if (ans == -1) {
printf("Orz, I cannot find x!\n");
} else {
printf("%lld\n", ans);
}
}
}
}
return 0;
}