pollard_rho

master
serr 2025-02-23 20:23:08 +03:00
commit 09451a3b37
1 changed files with 66 additions and 0 deletions

66
pollard_rho.py Normal file
View File

@ -0,0 +1,66 @@
import time
# ро-метод Полларда для дискретного логарифмирования
# Задача - найти такое x, что выполняется a^x ≡ b (mod p)
def gcd(a, b):
r0, r1 = a, b
x0, y0, x1, y1 = 1, 0, 0, 1
while r1 != 0:
q = r0 // r1
x0, x1 = x1, x0 - q * x1
y0, y1 = y1, y0 - q * y1
r1, r0 = r0 % r1, r1
if r1 > r0 >> 1:
r1 = r0 - r1
x1 = x0 - x1
y1 = y0 - y1
return x0, y0, r0
def v(a, b):
"""Возвращает абсолютно наименьший вычет числа a по модулю числа b"""
r1 = a % b
r2 = r1 - b
return r1 if abs(r1) < abs(r2) else r2
def order(a, p):
"""Возвращает порядок числа a по модулю числа p"""
i, x = 1, 0
while x != 1:
x, i = pow(a, i, p), i + 1
return i - 1
def f(c, a, b, p, log):
if c < 0:
log[0] += 1
return v(a * c, p)
else:
log[1] += 1
return v(b * c, p)
def solve(a, b, m):
d = gcd(a, m)[2]
a1, b1, m1 = a // d, b // d, m // d
x0 = b1 * gcd(a1, m1)[0]
return x0 % m
def pollard_rho(a, b, p, ord=0):
u, v = 1, 1
d = c = pow(a, u, p) * pow(b, v, p) % p
log_c, log_d = [1, 1], [1, 1]
while True:
#start_time = time.perf_counter()
c = f(c, a, b, p, log_c)
d = f(f(d, a, b, p, log_d), a, b, p, log_d)
#end_time = time.perf_counter()
#print(f"Время выполнения итерации: {end_time - start_time:.10f}")
# print(c, d, log_c, log_d)
if c == d: break
if ord == 0: ord = order(a, p)
#print(f"{log_c[0]}+{log_c[1]}x≡{log_d[0]}+{log_d[1]}x(mod{ord})")
#print(f"{log_c[1]-log_d[1]}x≡{log_d[0]-log_c[0]}(mod{ord})")
return solve(log_c[1]-log_d[1], log_d[0]-log_c[0], ord)
print(pollard_rho(2, 7, 137))
# print(pollard_rho(2,11,50091285122438801159, ord=25045642561219400579))