BSGS算法(大小步算法)

Posted waautomaton

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BSGS算法(大小步算法)相关的知识,希望对你有一定的参考价值。

$BSGS$ 算法 $Baby Steps Giant Steps$.

致力于解决给定两个互质的数 $a, p$ 求一个最小的非负整数 $x$ 使得 $a^xequiv b(mod p)$ 其中 $b$ 为任意正整数,$2≤a<p$,$2≤b<p$

该算法使用的原理与欧拉定理有关,其中$a, p$互质

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

又因为

                  $a^0equiv 1(mod p)$

所以$0到phi p$是一个循环节,也就是说该算法最多查找$phi (p)$次就可以找到答案,否则就无解。

设$x=im-k$其中$0≤k≤m$ 原式变为 

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

两边乘以$a^k$得到

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

然后我们可以拆成左右两部分分别进行枚举$i$和$k$。

①先枚举$k$,把对应的结果$a^kb$和对应的$k$放入$map$中,$map\_name[a^kb]=k$。$(k from 0 to m)$

②然后枚举$i$,把得到的结果$a^{im}$在$map$中进行查找,如果$map\_name.count(a^{im})$可以找到,则输出此时的$im-k$即可。($i from 1 to m$)

如果超出查找范围还没找到,则无解。

这里注意下,对$a^{im}$枚举时,要先快速幂预处理出来$a^m$,然后枚举$i$即可。

 

算法时间复杂度为$O(max(m, phi (p)/m))$.

最坏情况为$p$为质数$phi (p)=p-1$

此时将$m$取$sqrt p$为最小,时间复杂度为$O(sqrt p)$。

$m$取$sqrt p+1$或$ceil(sqrt p)$。

例题:P3846 [TJOI2007]可爱的质数

代码:

 

#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()
{

    ios::sync_with_stdio(0);

    cin.tie(0); cout.tie(0);
    cin >> p >> b >> n;
    ll m = ceil(sqrt(p));   /*算法复杂度O( max(m, phi(p)/m) ) 所以m取ceil(sqrt(p))最快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 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;
}

以上是关于BSGS算法(大小步算法)的主要内容,如果未能解决你的问题,请参考以下文章

bsgs算法

BSGS算法初探

BSGS算法

BSGS算法及拓展

BSGS算法(大步小步算法)

bsgs(Baby Steps Giant Steps)算法