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)$。
$Link$
费马小定理详见博客筛素数方法(二)—— 费马小定理及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算法初探的主要内容,如果未能解决你的问题,请参考以下文章