Загрузка данных


def gf128_inv(x):
    """
    Инверсия в GF(2^128) через расширенный алгоритм Евклида.
    Полином: x^128 + x^7 + x^2 + x + 1
    """
    if x == 0:
        raise ZeroDivisionError("0 не имеет обратного")
    
    # Полином MOD = x^128 + x^7 + x^2 + x + 1 = (1 << 128) | 0x87
    MOD = (1 << 128) | 0x87
    
    # Полиномиальные операции над GF(2)
    def poly_deg(a):
        return a.bit_length() - 1 if a else -1
    
    def poly_divmod(a, b):
        """Деление полиномов с остатком."""
        q = 0
        while a and poly_deg(a) >= poly_deg(b):
            shift = poly_deg(a) - poly_deg(b)
            q ^= (1 << shift)
            a ^= (b << shift)
        return q, a
    
    def poly_mul(a, b):
        """Умножение полиномов (без редукции)."""
        result = 0
        while b:
            if b & 1:
                result ^= a
            a <<= 1
            b >>= 1
        return result
    
    def poly_mod(a, m):
        """Приведение по модулю m."""
        while poly_deg(a) >= poly_deg(m):
            shift = poly_deg(a) - poly_deg(m)
            a ^= (m << shift)
        return a
    
    # Расширенный Евклид
    r0, r1 = MOD, x
    s0, s1 = 0, 1
    
    while r1 != 0:
        q, r = poly_divmod(r0, r1)
        r0, r1 = r1, r
        s0, s1 = s1, s0 ^ poly_mul(q, s1)
        # Приводим s0, s1 по модулю
        s0 = poly_mod(s0, MOD)
        s1 = poly_mod(s1, MOD)
    
    # r0 = gcd(MOD, x) = 1
    # s0 * x = r0 mod MOD = 1
    return s0 & MASK128