BSGS(Baby-Step Giant-Step)算法

BSGS (Baby-Step Giant-Step) 算法

作用:求满足 \(a^t \equiv b \ (mod \ p)\) 的最小的正整数 \(t\),保证 \(a\)\(p\) 互质。

方法:由欧拉定理:

\[a^{\phi(p)} \equiv 1 \ (mod \ p) \]

有:

\[ a^t \equiv a^{x \ mod \ \phi(p)} \ (mod \ p) \ \ \ \ \ \ t \in [0, \phi(p) - 1] \]

这里为了方便我们将 \(t\) 的右端点取为 \(p\) ,之后采用分块思想,将 \(t\) 的取值分为 \(k\) 块,其中 \(k = \lceil \sqrt{p} \rceil = \lfloor \sqrt{p} \rfloor + 1\)

\(t\) 可以用 \(k\) 进行表示:

\[t = kx - y \ \ \ \ \ x \in [1,k] \ \ \ \ \ y \in [0, k - 1] \]

此时 \(t\) 的取值范围是 \([1, k^2]\),因此该表示包含了 \(t\) 的所有可能取值。

这里 \(x\) 从 1 开始,防止 \(t\) 出现负数。

\(t = kx - y\) 而不是 \(t = kx + y\) 的原因是:

\[a^t = a^{kx-y} \equiv b \ (mod \ p) \\ \Rightarrow a^{kx} \equiv ba^{y} \ (mod \ p) \]

这里就不需要先计算逆元了,简化代码。

故该问题转化为:对于某一 \(x\),判断是否存在 \(y\),使得 \(x,y\) 满足 \(a^{kx} \equiv ba^{y} \ (mod \ p)\)

显然该问题可以用哈希表解决,即:

  • \(b * a^y \ (mod \ p)\) 用哈希表进行存储
  • 存储 \(b * a^y \ (mod \ p)\) 的值对应哪个 \(y\),如果有多个 \(y\),取最大的 \(y\)(因为这样的 \(t\) 会更小)

最后对于所有满足条件的 \(x, y\),取最小的 \(t\) 即可,由于 \(x\) 从 1 开始取,因此还需要特判一下 \(t=0\) 的情况,该算法的时间复杂度为 \(O(\sqrt{p})\)

模板题:BSGS

AC代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<unordered_map>
using namespace std;
using ll = long long;
int a, p, b;

ll bsgs(int a, int p, int b) {
    if(1 % p == b % p)  return 0;
    unordered_map<int, int> ump;
    int k = sqrt(p) + 1;
    //求b*a^ymodp
    for (int i = 0, j = b % p; i < k; i ++) {
        ump[j] = i;
        j = (ll)j * a % p;
    }
    
    //求a^k
    int ak = 1;
    for (int i = 1; i <= k; i ++) {
        ak = (ll)ak * a % p;
    }
    
    //求a^k^x
    for (int i = 1, j = ak % p; i <= k; i ++) {
        if(ump.count(j))    return (ll)k * i - ump[j];
        j = (ll)j * ak % p;
    }
    
    return -1;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    while(cin >> a >> p >> b, a || p || b) {
        ll res = bsgs(a, p, b);
        if(res == -1) {
            cout << "No Solution" << '\n';
            continue;
        }
        cout << res << '\n';
    }
    
    return 0;
}

扩展BSGS

将上述题意改为:求满足 \(a^t \equiv b \ (mod \ p)\) 的最小的正整数 \(t\)保证 \(a\)\(p\) 互质。

分类讨论:

  1. \(t = 0\) 时特判即可
  2. \(t \geq 1\) 时,设 \(gcd(a,p) = d\)
    • \(d = 1\) 采用朴素BSGS处理
    • \(d > 1\) 则对原式进行处理:

      \[ a^t \equiv b \ (mod \ p) \\ \Rightarrow a^t + kp = b \\ \Rightarrow \frac{a}{d} \cdot a^{t-1} + k \cdot \frac{p}{d} = \frac{b}{d} \\ \Rightarrow \frac{a}{d} \cdot a^{t-1} \equiv \frac{b}{d} \ (mod \ p) \\ ∵ gcd(\frac{a}{d}, \frac{p}{d}) = 1 \\ ∴ a^{t-1} \equiv \frac{b}{d} \cdot (\frac{a}{d})^{-1} \ (mod \ \frac{p}{d}) \]

    \(t^{'} = t-1, b^{'}=\frac{b}{d} \cdot (\frac{a}{d})^{-1},p^{'} = \frac{p}{d}\),则上述式子等价于:

    \[a^{t^{'}} \equiv b^{'} \ (mod \ p^{'}) \]

    \(a\)\(p^{'}\) 互质,则转化为朴素BSGS,否则根据上述转化进行递归,直到其互质为止,由于 \(p\) 的因子 \(d\) 的个数有限,因此只需递归有限次即可停止。

模板题:扩展BSGS

AC代码:


posted @ 2024-07-25 15:38  弱弱的Ray  阅读(111)  评论(0)    收藏  举报