核心概述

离散对数(Discrete Log):求解 a^x ≡ b (mod m) 的最小非负整数解 x;常用 Baby-Step Giant-Step(BSGS)算法,时间与空间均为 O(√m)。当 gcd(a,m)≠1 时用扩展 BSGS(exBSGS)分解公因子后再求。

原文引述

Description: Solves a^x ≡ b (mod m). Uses baby-step giant-step in O(√m) time and memory when gcd(a,m)=1, and an extended variant that handles non-coprime cases by factoring out gcds first. Time: O(√m) time, O(√m) memory Status: tested

展开阐述

  • 函数/接口(据实现)

    • discreteLog(a, b, m) → x 或 -1:返回最小非负解 x;若无解返回 -1。
    • 可选:当 m 为素数且已知 a 的阶分解时,可用 Pohlig–Hellman 进一步加速(本条仅说明,模板通常提供 BSGS/exBSGS)。
  • 核心算法A(BSGS,要求 gcd(a,m)=1)

    • 设 n = ⌈√m⌉。
    • 预处理“婴儿步”(baby steps):存表 H[a^j mod m] = j,j=0..n-1。
    • 计算 inv = a^{-n} (mod m)(用088-数论-模逆091-数论-模幂),令 cur = b。
    • 巨人步(giant steps):对 i=0..n:
      • 若 cur 在 H 中,解为 x = i·n + H[cur]。
      • 否则令 cur = cur · inv mod m,继续。
    • 若遍历完仍未命中,判无解。
    • 正确性:x = i·n + j 使 a^{i·n}·a^j ≡ b ⇒ b·(a^{-n})^i ≡ a^j。
  • 核心算法B(exBSGS,处理 gcd(a,m)≠1)

    • 设 k=0,acc=1。
    • 循环 g=gcd(a,m):
      • 若 b%g≠0,返回 -1(无解)。
      • 否则 m←m/g,b←b/g,acc←acc·(a/g) mod m,k++。
      • 若 acc≡b (mod m),返回 k(此时 x=k 即解)。
      • 继续直到 gcd(a,m)=1。
    • 令 b’ = b · inv(acc) mod m(消去前缀),在模 m 下对 a、b’ 用 BSGS 求到的解 x’,返回 x = x’ + k。
    • 该过程相当于逐步把方程“拉入”可逆域,再在剩余模数上用 BSGS。
  • 边界与特判

    • b ≡ 1 (mod m) ⇒ x=0 为一解。
    • m=1 ⇒ 仅 0≡0 成立,按实现约定返回 0 或 -1。
    • a≡0 (mod m):仅当 b≡0 (mod m) 且 x≥1 有解;取最小者 x=1。
    • 需注意取模规范化:统一 0≤a,b<m。
  • 输出语义

    • 返回最小非负解 x;若不存在解返回 -1。
    • 对于存在多解的情况(如在某些非简化模数下),此返回约定仍取最小非负者。
  • 复杂度

    • 时间 O(√m),空间 O(√m);exBSGS 的前置 gcd/逆元/规模缩减为 O(log m)。
  • 使用与注意

关联节点