[SDOI 2011]计算器

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

Sample Output

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

Hint

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

题解

数论三合一。

第一问,快速幂。

第二问,扩欧求特解。

第三问,BSGS。

 1 //It is made by Awson on 2018.1.16
 2 #include <set>
 3 #include <map>
 4 #include <cmath>
 5 #include <ctime>
 6 #include <queue>
 7 #include <stack>
 8 #include <cstdio>
 9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define Abs(a) ((a) < 0 ? (-(a)) : (a))
17 #define Max(a, b) ((a) > (b) ? (a) : (b))
18 #define Min(a, b) ((a) < (b) ? (a) : (b))
19 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
20 using namespace std;
21 const LL MOD = 233333;
22 void read(LL &x) {
23     char ch; bool flag = 0;
24     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
25     for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
26     x *= 1-2*flag;
27 }
28 void write(LL x) {
29     if (x > 9) write(x/10);
30     putchar(x%10+48);
31 }
32 
33 LL t, l, a, b, c;
34 
35 map<LL, int>mp;
36 LL exgcd(LL a, LL b, LL &x, LL &y) {
37     if (b == 0) {x = 1, y = 0; return a; }
38     LL d = exgcd(b, a%b, x, y), t = x;
39     x = y, y = t-a/b*y;
40     return d;
41 }
42 LL quick_pow(LL a, LL b, LL c) {
43     LL ans = 1;
44     while (b) {
45     if (b&1) ans = ans*a%c;
46     a = a*a%c, b >>= 1;
47     }
48     return ans;
49 }
50 
51 LL BSGS(LL a, LL b, LL c) {
52     if (b == 1) return 0;
53     if (a == 0 && b != 0) return -1;
54     mp.clear();
55     LL tim = ceil(sqrt(c)), tmp = b%c;
56     for (int i = 0; i <= tim; i++) {
57     mp[tmp] = i, tmp = tmp*a%c;
58     }
59     LL t = tmp = quick_pow(a, tim, c);
60     for (int i = 1; i <= tim; i++) {
61     if (mp.count(tmp)) return tim*i-mp[tmp];
62     tmp = tmp*t%c;
63     }
64     return -1;
65 }
66 void work() {
67     read(t), read(l);
68     while (t--) {
69     read(a), read(b), read(c);
70     if (l == 1) write(quick_pow(a, b, c)), putchar('\n');
71     else if (l == 2) {
72         LL x, y; LL d = exgcd(a, c, x, y);
73         if (b%d) printf("Orz, I cannot find x!\n");
74         else {x = x*b/d, d = c/d; write((x%d+d)%d), putchar('\n'); }
75     }else {
76         LL ans = BSGS(a%c, b%c, c);
77         if (ans == -1) printf("Orz, I cannot find x!\n");
78         else write(ans), putchar('\n');
79     }
80     }
81 }
82 int main() {
83     work();
84     return 0;
85 }

 

posted @ 2018-01-16 09:19  NaVi_Awson  阅读(240)  评论(0编辑  收藏  举报