首页 > 其他 > 详细

[BZOJ 2242] [SDOI 2011] 计算器

时间:2019-01-27 18:42:06      阅读:160      评论:0      收藏:0      [点我收藏+]

Description

你被要求设计一个计算器完成以下三项任务:

  1. 给定 \(y,z,p\),计算 \(y^z \bmod p\) 的值;
  2. 给定 \(y,z,p\),计算满足 \(xy≡ z \pmod p\) 的最小非负整数;
  3. 给定 \(y,z,p\),计算满足 \(y^x ≡ z \pmod p\) 的最小非负整数。

Input

输入包含多组数据。

第一行包含两个正整数 \(T,K\),分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。

以下行每行包含三个正整数 \(y,z,p\),描述一个询问。

Output

对于每个询问,输出一行答案。

对于询问类型 \(2\)\(3\),如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。

Sample Input

3 1
2 1 3
2 2 3
2 3 3
3 2
2 1 3
2 2 3
2 3 3

Sample Output

2
1
2
2
1
0

HINT

\(1\le y,z,p\le 10^9\)\(p\)为质数,\(1\le T\le10\)

Solution

询问 \(2\)

\[ ax\equiv b\pmod p\ \Downarrow\ax-kp=b \]

该方程有解的充要条件为 \(\gcd(a,p)\mid b\),答案为 \(b\times a^{-1}\bmod p\)

询问 \(3\)

给定 \(a,b,p\),求最小的非负整数 \(x\),满足

\[ a^x\equiv b\pmod p \]

根据费马小定理可知

\[ a^x\equiv a^{x \bmod p-1}\pmod p \]

因此 \(x\)\(0\) 枚举到 \(p-2\) 即可。

\(m={\left\lceil\sqrt p\right\rceil},x=i\times m-j\),有

\[ a^{i\times m-j}\equiv b\pmod p \]

移项得

\[ (a^m)^i\equiv a^jb\pmod p \]

首先从 \(0\dots m\) 枚举 \(j\),将得到的 \(a^jb\) 的值存入 \(hash\) 表中,然后从 \(1\dots m\) 枚举 \(i\),若表中存在 \((a^m)^i\),则当前 \(i\times m-j\) 即为答案。

Code

#include <cmath>
#include <cstdio>
#include <tr1/unordered_map>
#define ma hash

std::tr1::unordered_map<int,int> hash;

int read() {
    int x = 0; char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    return x;
}
int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}
int fastpow(int a, int b, int p) {
    int res = 1;
    for (; b; b >>= 1, a = 1LL * a * a % p)
        if (b & 1) res = 1LL * res * a % p;
    return res;
}
void bsgs(int a, int b, int p) {
    if (!a && !b) { puts("1"); return; }
    if (a % p == 0) { puts("Orz, I cannot find x!"); return; }
    int m = ceil(sqrt(p)), t = 1;
    hash.clear(), hash[b % p] = 0;
    for (int i = 1; i <= m; ++i)
        t = 1LL * t * a % p, hash[1LL * t * b % p] = i;
    a = t;
    for (int i = 1; i <= m; ++i, t = 1LL * t * a % p)
        if (hash.count(t)) { printf("%d\n", i * m - hash[t]); return; }
    puts("Orz, I cannot find x!");
}
int main() {
    int T = read(), K = read();
    while (T--) {
        int a = read(), b = read(), p = read();
        if (K == 1) printf("%d\n", fastpow(a, b, p));
        else if (K == 2) {
            if (b % gcd(a, p)) puts("Orz, I cannot find x!");
            else printf("%lld\n", 1LL * b * fastpow(a, p - 2, p) % p);
        } else bsgs(a, b, p);
    }
    return 0;
}

[BZOJ 2242] [SDOI 2011] 计算器

原文:https://www.cnblogs.com/fly-in-milkyway/p/10322617.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!