BSGS算法初探

Posted chenxiaoran666

tags:

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

前言

$BSGS$算法,全称$Baby Step Giant Step$,即大小步算法。某些奆佬也称其为(Ba)(Shan)(Gai)(Shi)算法。

它的主要作用是求解形式如$x^tequiv y(mod MOD)$的式子中$t$的值。

而且,它是一个简单易懂的算法(毕竟连我这样的数学渣渣都能理解)。


一个简单的性质

首先,我们需要知道一个简单的性质。

费马小定理可得,$x^{MOD-1}equiv1(mod MOD)$。

费马小定理详见博客筛素数方法(二)—— 费马小定理及MR素数判断

因此,当$tge MOD-1$时,会出现一个循环节。

于是我们就能保证答案$t$如果存在,则必然$<MOD-1$

这是一个简单而又重要的性质。


$BSGS$算法的主要思想

$BSGS$算法的主要思想就是两个字:分块(提到分块就要$%$一波分块奆佬$hl666$)。

根据分块思想,我们设一个变量$Size=sqrt{MOD}$(注意,此处要用$ceil$函数向上取整,这样才能保证$Size*Sizege MOD$,不然可能会遗漏答案)。

不难发现,此时的$t$可以表示为$i*Size-j$($i,j$均为非负整数且$j<Size$)。

那么原式就被转化成了$x^{i*Size-j}equiv y(mod MOD)$。

移项得$x^{iSize}equiv x^jy(mod MOD)$。

然后怎么处理呢?

我们可以对$x^j*y$的值进行一波预处理,用一个$map$存储下来。

然后枚举$i$,判断$x^{i*Size}$的值是否存在即可。

当找到一个合法的$i$后,最终的答案就是$i*Size-j$。


时间复杂度分析

预处理的时间复杂度显然是$O(j)$的,枚举$i$的时间复杂度显然是$O(i)$的。

又由于$i$和$j$都是$O(sqrt N)$大小的,所以总复杂度也是$O(sqrt N)$级别的,是一个比较优秀的算法。


代码

map<int,int> s;//定义一个map
inline int BSGS(int x,int y,int MOD)//对于一个式子x^t=y(mod MOD),求出t的值
{
    register int i,t=1,base,Size=ceil(sqrt(MOD));//注意此处要用ceil函数向上取整
    for(i=0;i<=Size;++i) s[1LL*t*y%MOD]=i,base=t,t=1LL*t*x%MOD;//预处理将(x^j)*y的值全部用map存下对应的j,并用base存储下x^Size
    for(i=1;i<=Size;++i,x=1LL*x*base%MOD)//枚举i,每次将t乘上x^Size 
        if(s[t]) return i*Size-s[t];//找到一个合法的i,则答案就是i*Size-j
    return 0;//无解返回0
}

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

BSGS算法

BSGS算法(大小步算法)

BSGS算法及拓展

BSGS算法!

BSGS算法(大步小步算法)

bsgs(Baby Steps Giant Steps)算法