Poj 3243 clever y evaluate a ^ x = B (mod C)/babystep_giantstep

Source: Internet
Author: User

Ask for the smallest X to make a ^ x = B (mod C)

Question:

[Expand the baby step giant step to solve the discrete logarithm problem]
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.

#include<cstdio>#include<cstring>#include<cmath>using namespace std;#define lint __int64#define MAXN 131071struct HashNode { lint data, id, next; };HashNode hash[MAXN<<1];bool flag[MAXN<<1];lint top;void Insert ( lint a, lint b ){    lint k = b & MAXN;    if ( flag[k] == false )    {        flag[k] = true;        hash[k].next = -1;        hash[k].id = a;        hash[k].data = b;        return;    }    while( hash[k].next != -1 )    {        if( hash[k].data == b ) return;        k = hash[k].next;    }    if ( hash[k].data == b ) return;    hash[k].next = ++top;    hash[top].next = -1;    hash[top].id = a;    hash[top].data = b;}lint Find ( lint b ){    lint k = b & MAXN;    if( flag[k] == false ) return -1;    while ( k != -1 )    {        if( hash[k].data == b ) return hash[k].id;        k = hash[k].next;    }    return -1;}lint gcd ( lint a, lint b ){    return b ? gcd ( b, a % b ) : a;}lint ext_gcd (lint a, lint b, lint& x, lint& y ){    lint t, ret;    if ( b == 0 )    {        x = 1, y = 0;        return a;    }    ret = ext_gcd ( b, a % b, x, y );    t = x, x = y, y = t - a / b * y;    return ret;}lint mod_exp ( lint a, lint b, lint n ){    lint ret = 1;    a = a % n;    while ( b >= 1 )    {        if( b & 1 )            ret = ret * a % n;        a = a * a % n;        b >>= 1;    }    return ret;}lint BabyStep_GiantStep ( lint A, lint B, lint C ){    top = MAXN;  B %= C;    lint tmp = 1, i;    for ( i = 0; i <= 100; tmp = tmp * A % C, i++ )        if ( tmp == B % C ) return i;    lint D = 1, cnt = 0;    while( (tmp = gcd(A,C)) !=1 )    {        if( B % tmp ) return -1;        C /= tmp;        B /= tmp;        D = D * A / tmp % C;        cnt++;    }    lint M = (lint)ceil(sqrt(C+0.0));    for ( tmp = 1, i = 0; i <= M; tmp = tmp * A % C, i++ )        Insert ( i, tmp );    lint x, y, K = mod_exp( A, M, C );    for ( i = 0; i <= M; i++ )    {        ext_gcd ( D, C, x, y ); // D * X = 1 ( mod C )        tmp = ((B * x) % C + C) % C;        if( (y = Find(tmp)) != -1 )            return i * M + y + cnt;        D = D * K % C;    }    return -1;}int main(){    lint A, B, C;    while( scanf("%I64d%I64d%I64d",&A,&C,&B ) !=EOF )    {        if ( !A && !B && !C ) break;        memset(flag,0,sizeof(flag));        lint tmp = BabyStep_GiantStep ( A, B, C );        if ( tmp == -1 )puts("No Solution");        else printf("%I64d\n",tmp);    }    return 0;}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.