[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)的最小非负整数。

Input

 输入包含多组数据。

第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
以下行每行包含三个正整数y,z,p,描述一个询问。

Output

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

Sample Input

【样例输入1】
3 1
2 1 3
2 2 3
2 3 3
【样例输入2】
3 2
2 1 3
2 2 3
2 3 3
【数据规模和约定】
对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。

Sample Output

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

HINT

Source

喜闻乐见的简单数学3合1,第一问直接快速幂,第二问EXGCD,第三问BSGS,注意特判y = 0的情况

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
    int f = 0, ch = 0; x = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    if(f) x = -x;
}
#define int ll
int y, z, Mod;
map<int, int> mp;
inline int gcd(int a, int b){ return b ? gcd(b, a % b) : a; }
inline int pow(int a, int b){
    int ans = 1;
    for(; b; b >>= 1, a = a * a % Mod)
        if(b & 1) ans = ans * a % Mod;
    return ans % Mod;
}
inline int exgcd(int a, int b, int &x, int &y){
    if(!b) return x = 1, y = 0, a;
    int g = exgcd(b, a % b, y, x);
    return y -= (a / b) * x, g;
}
inline void Query1(){
    return (void) printf("%lld\n", pow(y, z));
}
inline void Query2(){
    int xx, yy, g = gcd(Mod, y);
    if(z % g != 0) puts("Orz, I cannot find x!");
    else{
        g = exgcd(y, Mod, xx, yy);
        printf("%lld\n", ((xx + Mod) % Mod) * (z / g) % Mod);
    }
}
inline void Query3(){
    y %= Mod;
    if(!y && !z) return (void) (puts("1"));
    if(!y) return (void) (puts("Orz, I cannot find x!"));
    int m = (int) sqrt(Mod); mp.clear();
    for(int i = 0; i < m; i++){
        int now = pow(y, i);
        if(!mp[now]) mp[now] = i + 1;
    }
    for(int i = 0; i <= Mod - 1; i += m){
        int now = z * pow(y, Mod - 1 - i) % Mod;
        if(mp[now]) return (void) (printf("%lld\n", i + mp[now] - 1));
    }
    puts("Orz, I cannot find x!");
}
main(void){
    int T, k; read(T), read(k);
    while(T--){
        read(y), read(z), read(Mod);
        if(k == 1) Query1();
        if(k == 2) Query2();
        if(k == 3) Query3();
    }
    return 0;
}
萌萌哒的代码>.<

猜你喜欢

转载自www.cnblogs.com/mangoyang/p/9248451.html