# BZOJ2242: [SDOI2011]计算器

## 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

## Solution

（一道题当T1,T2,T3用）

$已知量：Y\space P\space Z\space m\\ Y^x\space \equiv Z\space (mod\space p)\\ 求x\\ 设m=\lceil \sqrt{P} \rceil\\ 则x=i*m-j \\ Y^{i*m-j}\equiv Z(mod\space P)\\ Y^{i*m}\equiv(Z*Y^j) (mod\space P)\\$

#include <bits/stdc++.h>
#define ll long long

int T, k;
ll y, z, p;

ll power(ll a, ll b) {
ll ans = 1, base = a;
while(b) {
if(b & 1) ans = (ans * base) % p;
base = (base * base) % p;
b >>= 1;
}
return ans % p;
}

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

std::map<ll , ll> mp;
void bsgs() {
mp.clear(); z %= p;
ll m = std::sqrt(p); if(m % p) ++ m;
for(ll i = 0, tmp = 1; i <= m; i ++, tmp = tmp * y % p) {
mp[z * tmp % p] = i;
}
if(power(y , m) == 0) {
if(z == 1) puts("1");
else puts("Orz, I cannot find x!");
return;
}
for(ll i = 1; i <= m; i ++) {
ll tmp = power(y, i * m), j = mp[tmp];
if(j == 0) continue;
if(i * m - j >= 0) {
printf("%lld\n", i * m - j);
return;
}
}
puts("Orz, I cannot find x!");
}

int main() {
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
scanf("%d%d", &T, &k);
while(T--) {
scanf("%lld%lld%lld", &y, &z, &p);
if(k == 1) {
printf("%lld\n", power(y, z));
} else if(k == 2) {
ll a1, a2, g;
y %= p; z %= p;
g = exgcd(y ,p ,a1 ,a2);
if(z % g) puts("Orz, I cannot find x!");
else {
ll tmp = p / g;
a1 = ((a1 * z) % tmp + tmp) % tmp;
printf("%lld\n", a1);
}
} else bsgs();
}
return 0;
}

posted @ 2018-12-16 11:51  henry_y  阅读(140)  评论(0编辑  收藏  举报