Miller–Rabin 素数判定

$n - 1 = 2^s d$( $d$ は奇数)と表し、いくつかの底 $a$ について $a^d, a^{2d}, \ldots, a^{2^{s-1} d} \bmod n$ を調べます。 $n$ が素数なら、 $a^d \equiv 1$ になるか、どこかで $-1$ が現れます。 $n < 2^{64}$ なら、決まった 7 個の底( $n < 4759123141$ なら 3 個)で調べれば、必ず正しく判定できます。

$10^{12}$ 程度までなら 試し割り でも判定できますが、それより大きいときや、たくさんの数を判定するときに使います。素因数分解には Pollard’s rho 素因数分解 を使います。

コード

def is_prime(n):
    # 決定的 Miller–Rabin(n < 2^64 で正しい)
    if n < 2:
        return False
    for p in (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37):
        if n % p == 0:
            return n == p
    d = n - 1
    s = 0
    while d % 2 == 0:
        d //= 2
        s += 1
    if n < 4759123141:
        bases = (2, 7, 61)
    else:
        bases = (2, 325, 9375, 28178, 450775, 9780504, 1795265022)
    for a in bases:
        if a % n == 0:
            continue
        x = pow(a, d, n)
        if x == 1 or x == n - 1:
            continue
        for _ in range(s - 1):
            x = x * x % n
            if x == n - 1:
                break
        else:
            return False
    return True