码迷,mamicode.com
首页 > 编程语言 > 详细

BSGS算法初探

时间:2018-10-28 11:08:15      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:时间   ++i   block   分析   表示   details   mod   for   line   

前言

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

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

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


一个简单的性质

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

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

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

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

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

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


$BSGS$算法的主要思想

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

根据分块思想,我们设一个变量$Size=\sqrt{MOD}$(注意,此处要用$ceil$函数向上取整,这样才能保证$Size*Size\ge 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算法初探

标签:时间   ++i   block   分析   表示   details   mod   for   line   

原文地址:https://www.cnblogs.com/chenxiaoran666/p/BSGS.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!