bzoj2242 [SDOI2011]计算器

2242: [SDOI2011]计算器

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 4699  Solved: 1782
[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)的最小非负整数。

输入包含多组数据。

【样例输入1】
3 1
2 1 3
2 2 3
2 3 3
【样例输入2】
3 2
2 1 3
2 2 3
2 3 3
【数据规模和约定】

【样例输出1】
2
1
2
【样例输出2】
2
1
0

Source

#include <cstdio>
#include <cmath>
#include <map>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int T, K;
typedef long long ll;
ll y, z, p, x, block;
map <ll, ll> m;

ll qpow(ll a, ll b, ll mod)
{
ll res = 1;
while (b)
{
if (b & 1)
res = (res * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return res;
}

void solve1()
{
scanf("%lld%lld%lld", &y, &z, &p);
printf("%lld\n", qpow(y, z, p));
}

ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = 1;
y = 0;
return a;
}
ll temp = exgcd(b, a % b, x, y);
ll t = x;
x = y;
y = t - (a / b) * y;
return temp;
}

void solve2()
{
scanf("%lld%lld%lld", &y, &z, &p);
ll tx, ty, td;
td = exgcd(y, p, tx, ty);
if (z % td != 0)
puts("Orz, I cannot find x!");
else
{
tx = tx * (z / td) % p;
ll mmod = p / td;
tx = (tx % mmod + mmod) % mmod;
printf("%lld\n", tx);
}
}

void solve3()
{
scanf("%lld%lld%lld", &y, &z, &p);
m.clear();
if (y % p == 0)
{
puts("Orz, I cannot find x!");
return;
}
else
{
block = ceil(sqrt(p));
ll ans;
for (int i = 0; i <= block; i++)
{
if (i == 0)
{
ans = z % p;
m[ans] = i;
continue;
}
ans = (ans * y) % p;
m[ans] = i;
}
ll t = qpow(y, block, p);
ans = 1;
for (int i = 1; i <= block; i++)
{
ans = (ans * t) % p;
if (m[ans])
{
ll t = i * block - m[ans];
printf("%lld\n", (t % p + p) % p);
return;
}
}
}
puts("Orz, I cannot find x!");
}

int main()
{
scanf("%d%d", &T, &K);
while (T--)
{
if (K == 1)
solve1();
if (K == 2)
solve2();
if (K == 3)
solve3();
}

return 0;
}

posted @ 2017-11-22 16:09  zbtrs  阅读(172)  评论(0编辑  收藏  举报