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=None): 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 == None: 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) if __name__ == "__main__": print(pollard_rho(2, 7123, 1123)) # print(pollard_rho(2,11,50091285122438801159, ord=25045642561219400579))