69 lines
1.4 KiB
Python
69 lines
1.4 KiB
Python
#!/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
|