離散對數&BSGS學習筆記
離散對數定義
求 \(k\) 使得 \(a^k \equiv n \pmod p\) ,稱 \(n\) 在模 \(p\) 意義下以 \(a\) 為底的對數是 \(k\) 。
如何求離散對數
BSGS(Baby Step,Giant Step)大步小步演算法可以求離散對數,它的思想是分塊思想。
首先要滿足 \(a \perp p\) ,因為在後面會需要把兩邊同時除以 \(a\) 的冪,所以需要 \(a \perp p\) 。
考慮樸素的演算法,我們可以列舉 \(k\) ,找到使得 \(a^k \equiv n \pmod p\) 的 \(k\) ,時間複雜度 \(O(p)\) ,但 \(p\) 一般都很大,所以考慮優化。
我們可以把 \(1\) 到 \(p\) 進行分塊,然後先一塊一塊地走,然後快到答案是再一個一個走,如果塊長是 \(m\) ,時間複雜度為 \(O(\max\{m,p/m\})\) ,不難發現,當 \(m = \sqrt n\) 時,時間複雜度是最優的 \(O(\sqrt p)\) ,這就是 BSGS 的思想,可以從名字裡看出。
具體實現:設一大步步長為 \(t\) ,大步步數為 \(i\) ,則 \(k=i \times t - r\) ,其中 \(r\) 是往回走小步的步數,把它代入上面的式子中可得:
\[a^{i\times t - r} \equiv n \pmod p \] \[a^{i\times t} \times a^{-r} \equiv n \pmod p \] \[a^{i \times t} \equiv n \times a^{r} \pmod p \]我們可以列舉大步步數(大步步長是確定的),然後每次判斷有沒有 \(r\)
code
int fpow(int a, int b, int p) {
if (b == 1)
return a;
int ans = fpow(a, b / 2, p);
ans = (1ll * ans * ans) % p;
if (b % 2 == 1)
ans = (1ll * ans * a) % p;
return ans;
}
int stp, r;
int nbr[50000], t;
map<int, int> mp;
int BSGS(int p, int b, int n) {
stp = sqrt(p), t = fpow(b, stp, p), nbr[0] = n % p;
for (int i = 1; i < stp; i++) { //注意這裡是小於,不然 n=1 時會掛
nbr[i] = (1ll * nbr[i - 1] * b) % p;
mp[nbr[i]] = i;
}
for (int i = 1, lt = t; 1ll * i * stp - stp <= p; i++, lt = (1ll * lt * t) % p)
if (mp[lt] > 0)
return 1ll * i * stp - mp[lt];
return -1;
}
BSGS 求階
當 \(a \perp p\) 時,最小的正整數 \(k\) 滿足 \(a^k \equiv 1\pmod p\) ,則稱 \(k\) 是 \(n\) 模 \(p\) 的階,記作 \(\delta_p(a)\) 或 \(Ord_p(a)\) 。
一個數的階就可以用 BSGS 來求,方法同上面一樣。
BSGS 的一些題目
P1082 [NOIP2012 提高組] 同餘方程
題意:求最小的正整數 \(x\) 滿足 \(ax \equiv 1 \pmod p\) 。
思路:
這題的題解貌似一篇 BSGS 的都沒有~~
BSGS 不只是可以求離散對數,這道題也可以做。我們設一大步步長為 \(t\) ,大步步數為 \(i\) ,則 \(x=i \times t - r\) ,其中 \(r\) 是往回走小步的步數,把它代入上面的式子中可得:
\[a\times(i \times t-r) \equiv 1 \pmod p \] \[a \times i \times t \equiv a \times r + 1 \pmod p \]所以我們就可以提前預處理出所有 \(1 \le r \le \sqrt p\) 的 \(ar+1\) 的值,然後列舉大步,每次 \(O(1)\) 判斷即可, 時間複雜度 \(O(\sqrt p \log p)\)。
P2485 [SDOI2011]計算器
題意:回答三種詢問,分別是:
-
\(y^z \mod p\) 的值。
-
滿足 \(xy \equiv z\pmod p\) 的最小整數 \(x\) 。
-
滿足 \(y^x \equiv z \pmod p\) 的最小整數 \(x\) 。
思路
操作一:直接快速冪即可。
操作二:BSGS 直接求,和上一道題幾乎一樣,就是把 \(ar+1\) 改成 \(ar+z\) 即可。
操作三:BSGS 原封不動就可以了。
時間複雜度:\(O(\sqrt p \log p)\) 或 \(O(\log z)\) 。