bsgs模板

这篇博客探讨了如何解决模指数运算的问题,即求解a^x = b (mod n)。文中介绍了两种算法:baby-step giant-step 和 Miller-Rabin 算法的变种。这两种方法特别适用于n为素数的情况,并且能在较短时间内找到0≤x<n的解。此外,还提供了一个C++实现的示例代码,展示了如何在实际编程中应用这些算法。
hash
//POJ 2417
//baby_step giant_step
// a^x = b (mod n) n为素数,a,b < n
// 求解上式 0 <= x < n的解
#include <cmath>
#include <cstdio>
#include <cstring>
#define MOD 76543
using namespace std;
int hs[MOD], head[MOD], next[MOD], id[MOD], top;
void insert(int x, int y)
{
    int k = x % MOD;
    hs[top] = x;
    id[top] = y;
    next[top] = head[k];
    head[k] = top++;
}
int find(int x)
{
    int k = x % MOD;
    for (int i = head[k]; i != -1; i = next[i])
        if (hs[i] == x)
            return id[i];
    return -1;
}
int BSGS(int a, int b, int n)
{
    memset(head, -1, sizeof(head));
    top = 1;
    if (b == 1)
        return 0;
    int m = sqrt(n * 1.0), j;
    long long x = 1, p = 1;
    for (int i = 0; i < m; i++, p = p * a % n)
        insert(p * b % n, i);
    for (long long i = m; ; i += m)
    {
        if ((j = find(x = x * p % n)) != -1)
            return i - j;
        if (i > n)
            break;
    }
    return -1;
}
int main()
{
    int a, b, n;
    while (~scanf("%d%d%d", &n, &a, &b))
    {
        int ans = BSGS(a, b, n);
        if (ans == -1)
            printf("no solution\n");
        else
            printf("%d\n", ans);
    }
}

map
ll BSGS(ll y,ll z,ll p) {
    map<ll,ll> ma;
    ll m=sqrt(p),tmp=0;
    if(y%p==0&&z==0) return 1;
    if(y%p==0&&z!=0) return -1;
    for(int i=0;i<=m;i++) {
        if(!i) {tmp=z%p;ma[tmp]=i;continue;}
        tmp=(tmp*y)%p;
        ma[tmp]=i;
    }
    tmp=1;ll t= power(y,m,p);
    for(int i=1;i*i<=p;i++) {
        tmp=(tmp*t)%p;
        if(ma[tmp])  {
            ll ans=i*m-ma[tmp];
            return ans;
        }
    }
    return -1;
}
<think> 我们被要求介绍BSGS算法(大步小步算法),根据用户提供的引用内容,用户已经对BSGS有了一定了解(如分块思想、扩展BSGS等),但希望获得更系统的介绍。 我们将按照以下结构组织回答: 1. 问题背景:离散对数问题 2. BSGS算法概述与适用条件(要求模数与底数互质) 3. 算法步骤(分块、建立哈希表、查找匹配) 4. 复杂度分析 5. 扩展BSGS(处理模数与底数不互质的情况) 6. 示例问题(可选,根据篇幅决定) 7. 相关扩展问题 注意:用户提供的引用中已经包含了BSGS的核心思想和扩展BSGS的推导,我们将整合这些信息,并严格按照格式要求(数学公式用$...$和$$...$$)进行表述。 </think> ### BSGS算法详解 BSGS(Baby-Step Giant-Step)算法是求解**离散对数问题**的高效算法,核心思想是通过**分块策略**将暴力枚举的复杂度$O(n)$降为$O(\sqrt{n})$。适用于解决形如: $$A^x \equiv B \pmod{P} \quad (\gcd(A,P)=1)$$ 的最小整数解$x$问题。 --- #### **算法原理与步骤** 1. **问题转化** 设$m = \lceil \sqrt{P} \rceil$,将解表示为: $$x = i \cdot m - j \quad (0 \leq j < m, 1 \leq i \leq m)$$ 则原方程转化为: $$A^{i \cdot m} \equiv B \cdot A^j \pmod{P}$$ 2. **Baby-Step(预处理)** 计算所有$j \in [0, m-1]$的$B \cdot A^j \mod P$并存入哈希表: ```python baby_steps = { (B * pow(A, j, P)) % P : j for j in range(m) } ``` 3. **Giant-Step(搜索匹配)** 计算$C = A^m \mod P$,枚举$i \in [1, m]$: $$T = C^i \mod P$$ 在哈希表中查找$T$,若存在$j$满足$T \equiv B \cdot A^j \pmod{P}$,则解$x = i \cdot m - j$。 4. **终止条件** - 找到匹配:返回$x = i \cdot m - j$ - 无匹配:方程无解 --- #### **复杂度分析** | 步骤 | 时间复杂度 | 空间复杂度 | |----------------|------------|------------| | Baby-Step | $O(\sqrt{P})$ | $O(\sqrt{P})$ | | Giant-Step | $O(\sqrt{P})$ | - | | **总计** | $O(\sqrt{P})$ | $O(\sqrt{P})$ | > 相比暴力枚举$O(P)$,效率提升显著($P=10^{18}$时,$\sqrt{P}=10^9$)。 --- #### **扩展BSGS(处理$\gcd(A,P)\neq1$)** 当$A$与$P$不互质时,需先消除公因子[^2]: 1. **提取公因子** 设$g=\gcd(A,P)$,若$g \nmid B$且$B \neq1$则无解。 方程两边同除$g$: $$A^{x-1} \cdot \frac{A}{g} \equiv \frac{B}{g} \pmod{\frac{P}{g}}$$ 2. **递归转化** 令$A' = A/g, P' = P/g, B' = B/g$,得到新方程: $$A^{x-1} \cdot A' \equiv B' \pmod{P'}$$ 递归至$\gcd(A', P')=1$后用标准BSGS求解。 --- #### **示例** 求解$5^x \equiv 17 \pmod{23}$的最小$x$: 1. 取$m = \lceil\sqrt{23}\rceil = 5$,计算$C=5^5 \mod 23 = 20$ 2. Baby-Step:计算$j \in [0,4]$的$17 \cdot 5^j \mod 23$ → `{17:0, 16:1, 11:2, 9:3, 22:4}` 3. Giant-Step: - $i=1$: $T=20^1 \mod 23=20$(不在表) - $i=2$: $T=20^2 \mod 23=9$ → 查表得$j=3$ 4. 解$x=2 \cdot 5 - 3 = 7$(验证:$5^7 \mod 23=17$ ✓) --- ### **应用场景** 1. 密码学中的离散对数难题(如Diffie-Hellman密钥交换) 2. 椭圆曲线密码体制的安全性分析 3. 区块链技术的私钥恢复场景(需合法授权)[^1] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值