#!/usr/bin/env python3 from random import randint from collections import Counter FACTOR_SIEVE = [] def primegen(n): sieve = [False] * n yield 2 for p in range(3, n, 2): if sieve[p]: continue for i in range(p**2, n, 2*p): sieve[i] = True yield p def iter_factors(n): sieve = init_factors(n) for i in range(n): yield pfactors(i, sieve) def init_factors(n): sieve = [False] * n for p in range(3, n, 2): if sieve[p]: continue for i in range(p**2, n, 2*p): sieve[i] = p return sieve def pfactors(n, sieve=FACTOR_SIEVE): if n < 1: if not n: return Counter() n = abs(n) fctrs = Counter() while not n % 2: fctrs[2] += 1 n //= 2 while sieve[n]: fctrs[sieve[n]] += 1 n //= sieve[n] if n != 1: fctrs[n] += 1 return fctrs def miller_rabin(n, k=10): if not (n % 2 and n % 3): return False d = n - 1 r = 0 while not r % 2: d //= 2 r += 1 for i in range(k): a = randint(2, n-2) x = pow(a, d, n) if x == 1 or x == n - 1: continue for j in range(r-1): x = pow(x, 2, n) if x == n - 1: break else: return False return True