$ 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; }