1. 程式人生 > >BSGS算法初探

BSGS算法初探

return 復雜度 ron 整數 tail 需要 作用 不難 art

前言

$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算法初探