POJ 3243 Clever Y(离散对数-拓展小步大步算法)

Description

Little Y finds there is a very interesting formula in mathematics:

XY mod Z = K

Given XYZ, we all know how to figure out K fast. However, given XZK, could you figure out Y fast?

Input

Input data consists of no more than 20 test cases. For each test case, there would be only one line containing 3 integers XZK (0 ≤ XZK ≤ 109). 
Input file ends with 3 zeros separated by spaces. 

Output

For each test case output one line. Write "No Solution" (without quotes) if you cannot find a feasible Y (0 ≤ Y < Z). Otherwise output the minimum Y you find.
 
题目大意:求离散对数。没有保证Z一定是素数。
PS:说一下上面没有提到的一个东西,最后一个O(sqrt(m))的循环中,逆元是没有必要每次都求的,可以预先求出来,让算法复杂度降至O(sqrt(m))。
在我的代码中,v = k^(-1) * a^(-i*m),可以在前面先求出k^(-1)和a^(-m),然后每次v都乘以a^(-m),而不需要每次对k*a^(i*m)求逆元。
 
代码(63MS):
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 const int SIZEH = 65537;
10 
11 struct hash_map {
12     int head[SIZEH], size;
13     int next[SIZEH];
14     LL state[SIZEH], val[SIZEH];
15 
16     void init() {
17         memset(head, -1, sizeof(head));
18         size = 0;
19     }
20 
21     void insert(LL st, LL sv) {
22         LL h = st % SIZEH;
23         for(int p = head[h]; ~p; p = next[p])
24             if(state[p] == st) return ;
25         state[size] = st; val[size] = sv;
26         next[size] = head[h]; head[h] = size++;
27     }
28 
29     LL find(LL st) {
30         LL h = st % SIZEH;
31         for(int p = head[h]; ~p; p = next[p])
32             if(state[p] == st) return val[p];
33         return -1;
34     }
35 } hashmap;
36 
37 void exgcd(LL a, LL b, LL &x, LL &y) {
38     if(!b) x = 1, y = 0;
39     else {
40         exgcd(b, a % b, y, x);
41         y -= x * (a / b);
42     }
43 }
44 
45 LL inv(LL a, LL n) {
46     LL x, y;
47     exgcd(a, n, x, y);
48     return (x + n) % n;
49 }
50 
51 LL pow_mod(LL x, LL p, LL n) {
52     LL ret = 1;
53     while(p) {
54         if(p & 1) ret = (ret * x) % n;
55         x = (x * x) % n;
56         p >>= 1;
57     }
58     return ret;
59 }
60 
61 LL BabyStep_GiantStep(LL a, LL b, LL n) {
62     for(LL i = 0, e = 1; i <= 64; ++i) {
63         if(e == b) return i;
64         e = (e * a) % n;
65     }
66     LL k = 1, cnt = 0;
67     while(true) {
68         LL t = __gcd(a, n);
69         if(t == 1) break;
70         if(b % t != 0) return -1;
71         n /= t; b /= t; k = (k * a / t) % n;
72         ++cnt;
73     }
74     hashmap.init();
75     hashmap.insert(1, 0);
76     LL e = 1, m = LL(ceil(sqrt(n + 0.5)));
77     for(int i = 1; i < m; ++i) {
78         e = (e * a) % n;
79         hashmap.insert(e, i);
80     }
81     LL p = inv(pow_mod(a, m, n), n), v = inv(k, n);
82     for(int i = 0; i < m; ++i) {
83         LL t = hashmap.find((b * v) % n);
84         if(t != -1) return i * m + t + cnt;
85         v = (v * p) % n;
86     }
87     return -1;
88 }
89 
90 int main() {
91     LL x, z, k;
92     while(cin>>x>>z>>k) {
93         if(x == 0 && z == 0 && k == 0) break;
94         LL ans = BabyStep_GiantStep(x % z, k % z, z);
95         if(ans == -1) puts("No Solution");
96         else cout<<ans<<endl;
97     }
98 }
View Code
原文地址:https://www.cnblogs.com/oyking/p/3633263.html