Módulo 6 · Teoria dos números e criptografia

Aritmética modular

Aula 6.1 · cerca de 18 minutos

a ≡ b (mod n) significa que n divide a − b: os dois deixam o mesmo resto. É a aritmética do relógio e dos inteiros de tamanho fixo. Um uint32 faz toda a aritmética mod 2³².

(a + b) mod n = ((a mod n) + (b mod n)) mod n
(a · b) mod n = ((a mod n) · (b mod n)) mod n

Essas propriedades permitem reduzir a cada passo e manter os números pequenos. É assim que hashes polinomiais (Rabin–Karp) e geradores congruenciais funcionam.

Exponenciação rápida

Calcular aᵉ mod n multiplicando e vezes é inviável para expoentes de 2048 bits. Elevando ao quadrado repetidamente, bastam O(log e) multiplicações:

def pow_mod(a, e, n):
    r = 1
    a %= n
    while e:
        if e & 1:
            r = r * a % n
        a = a * a % n
        e >>= 1
    return r

assert pow_mod(3, 200, 1_000_007) == pow(3, 200, 1_000_007)
Dica: Cuidado: em muitas linguagens, % com número negativo dá resultado negativo (-7 % 3 == -1 em C, Java e JS). Em Python dá 2. Para um resto sempre positivo: ((a % n) + n) % n.

Exercício 1

Qual é o último dígito de 7²⁰²⁵?

Exercício 2

Por que um hash de string costuma usar h = (h·31 + c) mod M, com M primo?