[POJ 2417]Discrete Logging

Description

Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that
    BL == N (mod P)

Input

Read several lines of input, each containing P,B,N separated by a space.

Output

For each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".

Sample Input

5 2 1
5 2 2
5 2 3
5 2 4
5 3 1
5 3 2
5 3 3
5 3 4
5 4 1
5 4 2
5 4 3
5 4 4
12345701 2 1111111
1111111121 65537 1111111111

Sample Output

0
1
3
2
0
3
1
2
0
no solution
no solution
1
9584351
462803587

Hint

The solution to this problem requires a well known result in number theory that is probably expected of you for Putnam but not ACM competitions. It is Fermat's theorem that states
   B(P-1) == 1 (mod P)
for any prime P and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat's theorem is that for any m
   B(-m) == B(P-1-m) (mod P) .

题解

 1 //It is made by Awson on 2018.1.15
 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 a, b, c, ans;
34 struct MAP {
35     LL ha[MOD+5]; int id[MOD+5];
36     void clear() {for (int i = 0; i < MOD; i++) ha[i] = id[i] = -1; }
37     int count(LL x) {
38     LL pos = x%MOD;
39     while (true) {
40         if (ha[pos] == -1) return 0;
41         if (ha[pos] == x) return 1;
42         ++pos; if (pos >= MOD) pos -= MOD;
43     }
44     }
45     void insert(LL x, int idex) {
46     LL pos = x%MOD;
47     while (true) {
48         if (ha[pos] == -1 || ha[pos] == x) {ha[pos] = x, id[pos] = idex; return; }
49         ++pos; if (pos >= MOD) pos -= MOD;
50     }
51     }
52     int query(LL x) {
53     LL pos = x%MOD;
54     while (true) {
55         if (ha[pos] == x) return id[pos];
56         ++pos; if (pos >= MOD) pos -= MOD;
57     }
58     }
59 }mp;
60 
61 LL quick_pow(LL a, LL b, LL c) {
62     LL ans = 1;
63     while (b) {
64     if (b&1) ans = ans*a%c;
65     a = a*a%c, b >>= 1;
66     }
67     return ans;
68 }
69 LL BSGS(LL a, LL b, LL c) {
70     mp.clear();
71     LL tim = ceil(sqrt(c)), tmp = b%c;
72     for (int i = 0; i <= tim; i++) {
73     mp.insert(tmp, i); tmp = tmp*a%c;
74     }
75     LL t = tmp = quick_pow(a, tim, c);
76     for (int i = 1; i <= tim; i++) {
77     if (mp.count(tmp)) return tim*i-mp.query(tmp);
78     tmp = tmp*t%c;
79     }
80     return -1;
81 }
82 void work() {
83     while (~scanf("%lld%lld%lld", &c, &a, &b))
84     if ((ans = BSGS(a, b, c)) == -1) printf("no solution
");
85     else write(ans), putchar('
');
86 }
87 int main() {
88     work();
89     return 0;
90 }
原文地址:https://www.cnblogs.com/NaVi-Awson/p/8288072.html