Author aekdycoin! [Normal baby step giant step] [Problem model] Solution 0 <= x <C in a ^ x = B (mod C), where C is a prime number. [Idea] We can make an equivalent X = I * m + J (0 <= I <m, 0 <= j <m) M = Ceil (SQRT (c )) The purpose of such decomposition is nothing more than to convert: (A ^ I) ^ M * A ^ J = B (mod C) Then you can solve the problem by doing a little violent work: (1) for I = 0-> M, insert Hash (I, a ^ I mod C) (2) Enumeration I. For each enumerated I, make AA = (a ^ m) ^ I mod C We have AA * a ^ J = B (mod C) Obviously, AA, B, and C are all known. Because C is a prime number(AA, c) 1 unconditionally Therefore, the number of solutions to this model equation is unique (it can be solved by extending Euclidean or Euler's theorem) For the obtained unique solution x, search in the hash table. If it is found, the return value isI * m + J Note:Due to the small to large enumeration of I, the J in the hash table must be the smallest element x in a residual system (that is, the indicator) Therefore, we can obtain the explain solution at this time. If you want to obtain a solution of x> 0, you only need to judge in the preceding step that the return value is when I * m + j> 0. So far, the above algorithms are not controversial, and the Code implemented by everyone is not much different. It can be seen that when C is a prime number, the problem of such discrete logarithm can become very easy to implement. [Expand the baby step giant step] [Problem model] Solution 0 <= x <C solution in a ^ x = B (mod C), and C unlimited (of course, the size is limited ......) [Preface] This problem is quite troublesome. There are many versions on the Internet,Most of them are nearly proven to be completely incorrectOf! I will not describe these practices here. The following is my practice (If you have any questions, please submit them.) The following describes the algorithm framework and provides a detailed proof later: (0) for I = 0-> 50 if (a ^ I mod c = B) return I O (50) (1) d <-0 d <-1 mod C While (TMP = gcd (a, c ))! = 1) { If (B % TMP) Return-1; // no solution! ++ D; C/= TMP; B/= TMP; D = D * A/tmp % C; } (2) M = Ceil (SQRT (c) // Ceil is necessary O (1) (3) for I = 0-> M insert hash table (I, a ^ I mod c) O (m) (4) k = pow_mod (a, m, c) For I = 0-> m Describe D * x = B (mod C)Unique Solution(If there is a solution, it must be unique !) Then query the hash table. If it is found (assuming J), return I * m + J + d Otherwise D = D * K % C, continue Loop (5) Return-1 unconditionally; // no solution! Below is the proof: Inference 1: A ^ x = B (mod C) Equivalent: A ^ A * a ^ B = B (mod C) (a + B) = x A, B> = 0 Proof: A ^ x = K * C + B (Modulo definition) A ^ A * a ^ B = K * C + B (a, B> = 0, a + B = X) So there are A ^ A * a ^ B = B (mod C) Inference 2: Make AA * a ^ B = B (mod C) The necessary condition for the solution is: at least one feasible solution a ^ B = x (mod c) can be obtained) Enable previous setup Inference 3 AA * a ^ B = B (mod C) The number of solutions is (AA, c) From inference 3, it is difficult to think of improvements to the original baby step giant step. For I = 0-> m For any solution that AA * x = B (mod C) If find x Return I * m + J According to inference 3, the complexity of the above algorithms actually degrades to almost O (c) When (AA, c) is very large) The reason is that (AA, c) is too large, and (a, c) is too large. So we need to find a solution that can reduce (a, c) without affecting the solution. The following describes a method of "elimination factor ". First D = 1 mod C For each consumption factor G = (a, c [I]) // C [I] indicates the value of C after the I-round elimination factor If G | B [I] // B [I] does not exist, it indicates the value of B after the I-round elimination factor. Direct return without Solution Otherwise B [I + 1] = B [I]/g C [I + 1] = C [I]/g D = D * A/G The specific implementation only requires several variables. For details, refer to the code. Assume that we have eliminated the' round (assume that the last obtained B and C are B 'and C' respectively ') So there are D * a ^ B = B '(mod C ') The algorithm can be obtained. For I = 0-> m Solution (D * (a ^ m) ^ I) * x = B '(mod C ') Because (D * (a ^ m) ^ I, C') = 1 (think about why ?) So we can get a unique solution. The next step is to find the unique solution in hash. In this way, we can get the value of B. Then, the explain solution is a' + B !! Now the problem is almost solved, but it seems that there are still bugs, that is For A ^ x = B (mod C) If the explain solution of X is <A', an error occurs. The minimum elimination factor is 2 for each consumption factor. Therefore, the maximum value of a' is log (c) Therefore, we can enumerate the 0-> log (c) solution brute-force. If a solution is obtained, the system returns Otherwise, there must be solutions x> log (c) PS. The above algorithms are based on hash tables. If map and other balancing trees are used for maintenance, the complexity will be greater. |