题目描述
原题来自:SDOI 2011
你被要求设计一个计算器完成以下三项任务:
给定 y,z,py,z,p,计算 y^x\bmod pyz
modp 的值;
给定 y,z,py,z,p,计算满足 x\times y\equiv z\ (\bmod p\ )x×y≡z (modp ) 的最小非负整数 xx;
给定 y,z,py,z,p,计算满足 y^x\equiv z\ (\bmod p\ )yx≡z (modp ) 的最小非负整数 xx。
输入
输入包含多组数据。
第一行包含两个正整数 T,KT,K 分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同);
以下 TT 行每行包含三个正整数 y,z,py,z,p,描述一个询问。
输出
对于每个询问,输出一行答案。
对于询问类型 22 和 33,如果不存在满足条件的,则输出 Orz, I cannot find x!,注意逗号与 I 之间有一个空格。
样例输入 Copy
【样例输入1】
3 1
2 1 3
2 2 3
2 3 3
【样例输入2】
3 2
2 1 3
2 2 3
2 3 3
样例输出 Copy
【样例输出1】
2
1
2
【样例输出2】
2
1
0
提示
数据范围与提示
对于全部数据,1\le y,z,p\le 10^9,1\le T\le 101≤y,z,p≤109,1≤T≤10,且保证 pp 为质数。
点击查看代码
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll y, z, p;
ll ksm(ll x, ll y, ll mod)
{
ll result = 1;
while (y > 0)
{
if (y % 2 == 0)
{
y = y / 2;
x = x * x % mod;
}
else
{
y--;
result = result * x % mod;
y = y / 2;
x = x * x % mod;
}
}
return result;
}
ll exgcd(ll a, ll b, ll &x, ll &yy)
{
if (b == 0)
{
x = 1;
yy = 0;
return a;
}
ll gcd = exgcd(b, a % b, x, yy);
ll tmp = x;
x = yy;
yy = tmp - a / b * yy;
return gcd;
}
ll BSGS(ll a, ll b, ll n)
{
a %= n;
b %= n;
if (a == 0)
return b == 0 ? 1 : -1;
if (b == 1)
return 0;
map<ll, ll> hash;
ll t = sqrt(n) + 1;
hash.clear();
for (int i = 0; i < t; i++)
{
ll x = b * ksm(a, i, n) % n;
hash[x] = i;
}
a = ksm(a, t, n);
for (int i = 1; i <= t; i++)
{
ll ans = ksm(a, i, n);
if (hash[ans])
return i * t - hash[ans];
}
return -1;
}
int main()
{
int t, k;
cin >> t >> k;
while (t--)
{
cin >> y >> z >> p;
if (k == 1)
cout << ksm(y, z, p) << "\n";
else if (k == 2)
{
ll x, yy;
ll gcd = exgcd(y, p, x, yy);
if (z % gcd)
cout << "Orz, I cannot find x!" << endl;
else
{
x = x * z / gcd;
x = (x % p + p) % p;
cout << x << endl;
}
}
else
{
ll ans = BSGS(y, z, p);
if (ans != -1)
cout << ans << "\n";
else
puts("Orz, I cannot find x!");
}
}
system("pause");
return 0;
}