[SDOI2011]计算器
题目描述
你被要求设计一个计算器完成以下三项任务:
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)的最小非负整数。
输入描述:
输入包含多组数据。
第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
以下行每行包含三个正整数y,z,p,描述一个询问。
输出描述:
对于每个询问,输出一行答案。对于询问类型2和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。
输入
3 1 2 1 3 2 2 3 2 3 3
输出
2 1 2
输入
3 2 2 1 3 2 2 3 2 3 3
输出
2 1 0
备注:
【数据规模和约定】
对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。
// 数论常见三种操作 #include<bits/stdc++.h> using namespace std; typedef long long LL; LL ksm(LL a, LL b, LL p) { LL ans = 1 % p; while (b) { if (b & 1) ans = ans * a % p; a = a * a % p; b >>= 1; } return ans; } LL exgcd(LL a, LL b, LL& x, LL& y) { if (b == 0) { x = 1; y = 0; return a; } LL d = exgcd(b, a % b, x, y); LL z = x; x = y; y = z - y * (a / b); return d; } LL baby_step_giant_step(LL a, LL b, LL p) { map<LL, LL> hash; hash.clear(); b %= p; LL t = sqrt(p) + 1; for (LL j = 0; j < t; j++) { LL val = b * ksm(a, j, p) % p; hash[val] = j; } a = ksm(a, t, p); if (a == 0) return b == 0 ? 1 : -1; for (LL i = 0; i <= t; i++) { LL val = ksm(a, i, p); LL j = hash.find(val) == hash.end() ? -1 : hash[val]; if (j >= 0 && i * t - j >= 0) return i * t - j; } return -1; } void solve(int tp) { LL y, z, p, x, t; cin >> y >> z >> p; if (tp == 1) { cout << ksm(y, z, p) << endl; } else if (tp == 2) { // y * x - z = p * t y * x + p * t = z LL g = exgcd(y, p, x, t); if (z % g) cout << "Orz, I cannot find x!" << endl; else { x *= z / g; p /= g; cout << (x % p + p) % p << endl; } } else { LL ans = baby_step_giant_step(y, z, p); if (ans == -1) cout << "Orz, I cannot find x!" << endl; else cout << ans << endl; } } int main() { int T, K; while (cin >> T >> K) { while (T--) { solve(K); } } return 0; }

浙公网安备 33010602011771号