BSGS algorithm (step size algorithm)

$ BSGS $ algorithm $ Baby \ Steps \ Giant \ Steps $.

Given to address two prime numbers $ a, \ p $ seeking a minimum non-negative integer such that $ X $ $ a ^ x \ equiv b (mod \ p) $ where $ b $ is any positive integer, $ 2≤a <p $, $ 2≤b <p $

The algorithm uses the principle of Euler's theorem about where $ a, \ p $ Coprime

                  $a^{\phi (p)}\equiv 1(mod\ p)$

also because

                  $a^0\equiv 1(mod\ p)$

So $ 0 to \ phi p $ is a circular section, that is to say up to find the algorithm $ \ phi (p) $ times you can find the answer, otherwise no solution.

Provided $ x = im-k $ where $ 0≤k≤m $ becomes the original formula 

                  $a^{im-k}\equiv b(mod\ p)$

Multiplying both sides to give $ a ^ k $

                  $a^{im}\equiv a^kb(mod\ p)$

Then we can split into two parts, left and right, respectively, to enumerate $ i $ and $ k $.

① First Enumeration $ k $, corresponding to the result of $ a ^ kb $ and the corresponding Map $ k $ $ $ placed in, $ map \ _name [a ^ kb] = k $. $ (K \ from \ 0 \ to \ m) $

$ I $ enumeration ② Then, the resultant $ a ^ {im} $ Map to find the $ $, if $ map \ _name.count (a ^ {im}) $ can be found, at this time the output $ im-k $ can be. ($ I \ from \ 1 \ to \ m $)

If you exceed Look not found, there was no solution.

Note that here, the time of the $ a ^ $ enumeration, first pre-flash power out {im} $ a ^ m $, $ I $ can then enumerated.

 

Calculation complexity is $ O (max (m, \ phi (p) / m)) $.

The worst case is a prime number $ p $ $ \ phi (p) = p-1 $

At this time, the take $ m $ $ \ sqrt p $ minimum, the time complexity is $ O (\ sqrt p) $.

$ M $ take $ \ sqrt p + 1 $ or $ ceil (\ sqrt p) $.

Example: P3846 [TJOI2007] cute primes

Code:

 

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int n, p, b;

unordered_map<ll, int> vis;
inline ll fp( ll a, ll b ){
    a %= p;
    ll res = 1;
    while( b ){
        if( b&1 ) res = res*a%p;
        b >>= 1;
        a = a*a%p;
    }
    return res;
}

int main()
{

    :: sync_with_stdio iOS ( 0 ); 

    cin.tie ( 0 ); cout.tie ( 0 ); 
    CIN >> B >> >> P n-; 
    LL m = ceil (sqrt (P));    / * algorithm complexity O (max (m, phi (p ) / m)) so that m is ceil (sqrt (p)) the fastest O (sqrt (P)) * / 
    LL tmp = n-;
     for ( int K = 0 ; K <= m ; K ++, (tmp = B *) =% P) { 
        VIS [tmp] = K; 
    } 
    LL T = FP (B, m); tmp = T;
     BOOL In Flag = 0 ;
     for ( int I =1; i<=m; i++, tmp=tmp*t%p ){
        if( vis.count(tmp) ){
            flag = 1;
            cout << i*m-vis[tmp] << endl;
            break;

        }
    }
    if(!flag) cout << "no solution" <<endl;

    return 0;
}

Guess you like

Origin www.cnblogs.com/WAautomaton/p/12048212.html