commit 09451a3b37f8c8e5d7ef578943c0c7ec7ece29ac Author: serr Date: Sun Feb 23 20:23:08 2025 +0300 pollard_rho diff --git a/pollard_rho.py b/pollard_rho.py new file mode 100644 index 0000000..69169d9 --- /dev/null +++ b/pollard_rho.py @@ -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)) \ No newline at end of file