The beauty of the original root G of the modulo prime p is reflected in the presence of a non-zero number G power of each modulo p. Therefore, for any number 1 <= A <P, we can select the power
G, G ^ 2, G ^ 2, ''', G ^ (P-2), G ^ (pm)
Exactly the same as model a P. The corresponding index is called G-based a model P. Assume that P and G have been given, the index is I ().
The following is in the form of all powers of 2 mod 13:
I 1 2 3 4 5 6 7 8 9 10 11 12
2 ^ I (mod 13) 2 4 8 3 6 12 11 9 5 10 7 1
For example, for I (11), we search for the second row of the table until the number of 11 is found, then metric I (11) = 7 can be obtained from the first row.
Metric rules
A). I (AB) = I (A) + I (B) (mod P-1)
B). I (a ^ K) = KI (A) (mod P-1)
G ^ I (AB) = AB = G ^ I (a) G ^ I (B) = G ^ (I (A) + I (B) (mod P)
Therefore, G ^ I (x) = x (mod P-1)
It can also be understood as follows: G ^ I (value) = ID (mod P-1)
Example: 3 * x ^ 30 = 4 (mod 37)
I (3 * x ^ 30) = I (4)
I (3) + 30 * I (x) = I (4) (mod 36)
26 + 30 * I (x) = 2 (mod 36)
30 * I (x) =-24 = 12 (mod 36)
I (4) = 2 here:
Actually G ^ 2 = 4 (mod 36)
In fact, this can be calculated based on G ^ x = B (mod P ).
For this question, G is the root 2 of 37, B = I (x) P = 36
That is, X that satisfies 2 ^ x = I (x) (mod 36. Use the baby step giant step algorithm.
Reminder: do not divide the two sides by 6 to get 5 * I (x) + 2 (mod 36); otherwise, some solutions will be lost.
Ax = C (mod m)
By extending Euclidean, note:
I (x) =
Finally, we have an indicator table (which is included in the book, so we don't want to write a program on our own) to get the corresponding value of X.
I (16) = 4, I (25) = 10, I (9) = 16
I (21) = 22, I (12) = 28, I (28) = 34
In fact, you can also use the original formula G ^ I (x) = x (mod P-1) of the metric)
Therefore, there are 6 solutions in the same formula 3 * x ^ 30 = 4 (mod 37), that is
X = 16,25, 9,21, 12,28 (mod 37)
/** Hrbeu1318.c ** created on: 2011-10-13 * Author: bjfuwangzhu */# include <stdio. h> # include <math. h> # include <string. h> # include <stdlib. h> # define ll long # define Nmax 4001 typedef struct num {int II, value;} num; num [Nmax]; int flag [Nmax], prime [Nmax], pfactor [Nmax], cpfactor [Nmax]; int Plen, len_pfactor, K, N, P, proot, X, Y; void mkprime () {int I, J; memset (Prime,-1, sizeof (PRIME); for (I = 2; I <Nmax; I ++) {If (prime [I]) {for (j = I + I; j <Nmax; j + = I) {Prime [J] = 0 ;}}for (I = 2, Plen = 0; I <Nmax; I ++) {If (prime [I]) {Prime [Plen ++] = I ;}} void findpfactor (int n) {int I, Te, CNT; Te = (INT) SQRT (1.0 * n ); for (I = 0, len_pfactor = 0; (I <Plen) & (prime [I] <= tE); I ++) {If (N % prime [I] = 0) {CNT = 0; while (N % prime [I] = 0) {CNT ++; n/= prime [I];} pfactor [len_pfactor] = prime [I]; Cpfactor [len_pfactor ++] = CNT ;}} if (n> 1) {pfactor [len_pfactor] = N; cpfactor [len_pfactor ++] = 1 ;}} /* Rapid power remainder a ^ B % C */INT modular_exp (int A, int B, int c) {ll res, temp; Res = 1% C, temp = A % C; while (B) {If (B & 1) {res = res * temp % C;} temp = temp * temp % C; B >>= 1 ;}return (INT) RES;} int DFS (INT depth, ll now) {int I; ll res, temp; If (depth = len_pfactor) {res = modular_exp (proot, now, P); If (Res = 1) & (now! = (P-1) {return 0;} return 1 ;}for (I = 0, temp = 1; I <= cpfactor [depth]; I ++) {If (! DFS (depth + 1, now * temp) {return 0;} temp = temp * pfactor [depth];} return 1;} void primitive () {findpfactor (p-1); For (proot = 2; proot ++) {If (DFS (0, 1) {return ;}}} int extend_gcd (int A, int B) {int D, xx; If (B = 0) {x = 1, y = 0; return ;} D = extend_gcd (B, A % B); xx = x; X = Y, y = XX-A/B * Y; return D;} int bfindnum (INT key, int N) {int left, right, mid; left = 0, Right = N; while (left <= ri Ght) {mid = (left + right)> 1; if (Num [Mid]. value = Key) {return num [Mid]. II;} else if (Num [Mid]. value> key) {right = mid-1;} else {left = Mid + 1;} return-1;} int CMP (const void * a, const void * B) {num n = * (Num *) A; num M = * (Num *) B; return n. value-M. value;}/* a ^ x = B (mod c) */INT baby_step_giant_step (int A, int B, int c) {int I, j, Te, AA; ll temp, xx; Te = (INT) (SQRT (1.0 * C) + 0.5); (I = 0, temp = 1% C; I <= tE; I ++) {num [I]. II = I; num [I]. value = (INT) (temp); temp = temp * A % C;} AA = num [Te]. value; qsort (Num, te + 1, sizeof (Num [0]), CMP); for (I = 0, temp = 1; I <= tE; I ++) {extend_gcd (INT) (temp), c); xx = (LL) x; xx = XX * B; xx = XX % C + C; X = (INT) (xx % C); j = bfindnum (x, te + 1); If (J! =-1) {return I * te + J;} temp = temp * Aa % C;} return-1;} int RCMP (const void * a, const void * B) {return * (int *) A-* (int *) B;}/* Ax = B (mod c) */INT result [Nmax]; void solve (int, int B, int c) {int I, d, CC; D = extend_gcd (a, c); If (B % d) {puts ("no solution! "); Return;} cc = C; B/= D, C/= D; Result [0] = (LL) x * B % C + C) % C; for (I = 1; I <D; I ++) {result [I] = (result [I-1] + C) % cc;} for (I = 0; I <D; I ++) {result [I] = modular_exp (proot, result [I], p);} qsort (result, D, sizeof (result [0]), RCMP); for (I = 0; I <D; I ++) {printf ("% d \ n ", result [I]) ;}} int main () {# ifndef online_judgefreopen ("data. in "," r ", stdin); # endifint A, B, C; mkprime ();/* x ^ K = N (Mod p) */while (~ Scanf ("% d", & K, & P, & N) {primitive (); B = baby_step_giant_step (proot, N, P ); A = K, c = p-1; solve (A, B, C); printf ("\ n") ;}return 0 ;}