''' The trial division algorithm is essentially the idea that all factors of an integer n are less than or equal to isqrt(n), where isqrt is floor(sqrt(n)). Moreover, if p divides n, then all other factors of n must be factors of n//p. Hence they must be <= isqrt(n//p). ''' from math import isqrt # integer square root # Returns the "multiplicity" of a prime factor def pf_multiplicity(n: int, p: int) -> int: mult = 0 while n % p == 0: n //= p mult += 1 return n, mult ''' Trial division prime factorisation algorithm. Returns a list of tuples (p, m) where p is a prime factor and m is its multiplicity. ''' def trial_division(n: int) -> list[tuple[int, int]]: factors = [] # determine multiplicity of the only even prime (2) n, mult_2 = pf_multiplicity(n, 2) if mult_2: factors.append((2, mult_2)) # determine odd factors and their multiplicities p = 3 mult = 0 limit = isqrt(n) while p <= limit: n, mult = pf_multiplicity(n, p) if mult: factors.append((p, mult)) limit = isqrt(n) # recalculate limit mult = 0 # reset else: p += 2 # if n is still greater than 1, then n is a prime factor if n > 1: factors.append((n, 1)) return factors