Baby-step Giant-step
概要
離散対数問題(Discrete Logarithm Problem)を解くアルゴリズム。
ある \(X, Y, M\) について \(X^K \equiv Y\) (mod \(M\)) となる \(K\) を求める。
具体的計算
1. Baby-step
\(m = \lceil \sqrt{M} \rceil\) とし、 \(X^0, X^1, ..., X^{m-1}\) を求めておく。
2. Giant-step
\(R = X^{-m}\) を計算し、 \(a = 0\) から \(Y \times R^a \equiv X^b\) (mod \(M\)) となる \(0 \le b \le m-1\) が見つかるまで計算する。 (この計算は高々 \(O(m)\) 回)
\(K = ma + b\) を解として出力する。
計算量
\(O(\sqrt{M})\)
実装
# X^K ≡ Y (mod M) となるような K を求める
def solve(X, Y, M):
D = {1: 0}
sq = int(M**.5)+1
# Baby-step
Z = 1
for i in range(sq):
Z = Z * X % M
D[Z] = i+1
if Y in D:
return D[Y]
# Giant-step
R = pow(Z, M-2, M) # R = X^(-sq)
for i in range(1, sq+1):
Y = Y * R % M
if Y in D:
return D[Y] + i*sq
return -1
X = 3; Y = 193; MOD = 10**9 + 7
r = solve(X, Y, MOD)
assert pow(X, r, MOD) == Y, (pow(X, r, MOD), Y)