79 lines
2.4 KiB
Python
79 lines
2.4 KiB
Python
from math import sqrt, floor
|
|
|
|
class sieve:
|
|
|
|
def __init__(self):
|
|
self.sieve = [False]
|
|
self._length = 1
|
|
self._target = 1
|
|
|
|
def run(self, n):
|
|
self._target = n
|
|
self._elongate()
|
|
|
|
def get(self, n):
|
|
if n > self._length:
|
|
self.run(n)
|
|
return self.sieve[n-1]
|
|
|
|
def _elongate(self):
|
|
length = self._length
|
|
target = self._target
|
|
diff = target - length
|
|
if diff > 0:
|
|
self.sieve += [True for _ in range(diff)]
|
|
for i in range(floor(sqrt(target))):
|
|
if self.sieve[i]:
|
|
_floor = length//(i+1)
|
|
_ceil = target//(i+1)
|
|
for j in range(_floor, _ceil):
|
|
actual = (i+1)*(j+1)-1
|
|
if actual > i+1:
|
|
self.sieve[actual] = False
|
|
self._length = target
|
|
|
|
class extended_sieve:
|
|
|
|
def __init__(self):
|
|
self.sieve = [[False, 1, []]]
|
|
self._length = 1
|
|
self._target = 1
|
|
self.prerun_step = 1000
|
|
|
|
def run(self, n):
|
|
self._target = n
|
|
self._elongate()
|
|
|
|
def get(self, n):
|
|
if n > self._length:
|
|
self.run(n+self.prerun_step)
|
|
prime_decomp = {}
|
|
for e in self.sieve[n-1][2]:
|
|
if e in list(prime_decomp.keys()):
|
|
prime_decomp[e] += 1
|
|
else:
|
|
prime_decomp[e] = 1
|
|
return [self.sieve[n-1][0], prime_decomp]
|
|
|
|
def _elongate(self):
|
|
length = self._length
|
|
target = self._target
|
|
diff = target - length
|
|
if diff > 0:
|
|
self.sieve += [[True, length+i+1, []] for i in range(diff)]
|
|
for i in range(target):
|
|
if self.sieve[i][0]:
|
|
if i+1 > length:
|
|
self.sieve[i][2] += [i+1]
|
|
_floor = length//(i+1)
|
|
_ceil = target//(i+1)
|
|
for j in range(_floor, _ceil):
|
|
actual = (i+1)*(j+1)-1
|
|
if actual > i+1:
|
|
old_entry = self.sieve[actual]
|
|
self.sieve[actual] = [False, old_entry[1]//(i+1), old_entry[2]+[i+1]]
|
|
elif self.sieve[i][1] != 1:
|
|
old_entry = self.sieve[i]
|
|
self.sieve[i] = [False, 1, old_entry[2]+self.sieve[old_entry[1]-1][2]]
|
|
self._length = target
|