Observation: for a given fraction, the number of steps before reducing is the number of steps before we hit the next smallest factor. We always reduce to 1 / another number and so we always eliminate all of the smallest factors. So f(n) = largest_prime_factor(n + 1) - 1. ''' from helpers import prime_factorizations, isPrimeMR, sieve limit = 2 * 10**6 primes = sieve(limit + 100) pfs = prime_factorizations(limit + 100) def get_pf(n): if n < len(pfs): return pfs[n] else: if isPrimeMR(n): return {n: 1} ans = {} for p in primes: if n < len(pfs) or isPrimeMR(n): break power = 0 while n % p == 0:
from helpers import prime_factorizations, sieve from operator import mul from sys import setrecursionlimit # bold call but you gotta do what you gotta do to not rewrite your shitty recursive solution into one using a stack :^)^)^)^)^)^)^)^)^) setrecursionlimit(10**4) N = 120000 prime_factorizations = prime_factorizations(N) primes = sieve(N) # print prime_factorizations def rad(n): return reduce(mul, prime_factorizations[n].keys()) def abc_hit(a, b, c): rad_factors = set(prime_factorizations[c].keys()) b_factors = set(prime_factorizations[b].keys()) a_factors = set(prime_factorizations[a].keys()) rad_factors = rad_factors.union(b_factors) rad_factors = rad_factors.union(a_factors) return reduce( mul, rad_factors) < c and a_factors.intersection(b_factors) == set() def possible_nums(prime_candidates, max_num, min_index):
from helpers import sieve, prime_factorizations, isPrimeMR primes = sieve(10**8) setprimes = set(primes) pfs = prime_factorizations(10**6) def get_divisors(pf): if len(pf) == 0: yield 1 return (prime, power) = pf.popitem() for p in range(power + 1): for divisor in get_divisors(pf): yield prime**p * divisor pf[prime] = power def get_pf(n): if n < len(pfs): return pfs[n] else: if isPrimeMR(n): return {n : 1} ans = {} for p in primes: if n < len(pfs) or n in setprimes: break power = 0 while n % p == 0:
We always reduce to 1 / another number and so we always eliminate all of the smallest factors. So f(n) = largest_prime_factor(n + 1) - 1. ''' from helpers import prime_factorizations, isPrimeMR, sieve limit = 2 * 10**6 primes = sieve(limit + 100) pfs = prime_factorizations(limit + 100) def get_pf(n): if n < len(pfs): return pfs[n] else: if isPrimeMR(n): return {n : 1} ans = {} for p in primes: if n < len(pfs) or isPrimeMR(n): break power = 0 while n % p == 0: power += 1
from helpers import sieve, prime_factorizations, isPrimeMR primes = sieve(10**8) setprimes = set(primes) pfs = prime_factorizations(10**6) def get_divisors(pf): if len(pf) == 0: yield 1 return (prime, power) = pf.popitem() for p in range(power + 1): for divisor in get_divisors(pf): yield prime**p * divisor pf[prime] = power def get_pf(n): if n < len(pfs): return pfs[n] else: if isPrimeMR(n): return {n: 1} ans = {} for p in primes: if n < len(pfs) or n in setprimes: break power = 0 while n % p == 0:
from helpers import prime_factorizations, sieve from operator import mul from sys import setrecursionlimit # bold call but you gotta do what you gotta do to not rewrite your shitty recursive solution into one using a stack :^)^)^)^)^)^)^)^)^) setrecursionlimit(10**4) N = 120000 prime_factorizations = prime_factorizations(N) primes = sieve(N) # print prime_factorizations def rad(n): return reduce(mul, prime_factorizations[n].keys()) def abc_hit(a, b, c): rad_factors = set(prime_factorizations[c].keys()) b_factors = set(prime_factorizations[b].keys()) a_factors = set(prime_factorizations[a].keys()) rad_factors = rad_factors.union(b_factors) rad_factors = rad_factors.union(a_factors) return reduce(mul, rad_factors) < c and a_factors.intersection(b_factors) == set() def possible_nums(prime_candidates, max_num, min_index): if min_index >= len(prime_candidates) or max_num < prime_candidates[min_index]: yield 1 return
from helpers import sieve, prime_factorizations from collections import defaultdict limit = 10**6 * 40 primes = sieve(limit) setprimes = set(primes) small_prime_factorizations = prime_factorizations(limit / 40) small_totient_chain_length = [0] def euler_phi(prime_factorization): answer = 1 for (prime, power) in prime_factorization.items(): answer *= prime - 1 answer *= prime**(power - 1) return answer def compute_chain_length(i): if i == 1: return 1 prime_factorization = small_prime_factorizations[i] phi_i = euler_phi(prime_factorization) return 1 + small_totient_chain_length[phi_i] def get_chain_length(n): if n < len(small_totient_chain_length): return small_totient_chain_length[n]
from helpers import prime_factorizations, crt, sieve from itertools import product ''' 153651073760956 [Finished in 2605.0s] ''' limit = 2 * 10**7 # N = 2 * 10 ** 7 pfs = prime_factorizations(limit / 20) primes = sieve(limit) setprimes = set(primes) def get_pf(n): if n < len(pfs): return pfs[n] else: if n in setprimes: return {n : 1} ans = {} for p in primes: if n < len(pfs) or n in setprimes: break power = 0 while n % p == 0: power += 1 n /= p
''' 659104042 [Finished in 177.4s] However, it needs like 4 GB of ram to run that fast. Turning down the number of pfs precomputed will reduce ram usage, but increase compute time. ''' limit = 10**7 modulus = 1000000007 pfs = prime_factorizations((limit + 1) / 2) n = limit primes = sieve(limit + 1) setprimes = set(primes) def get_pf(n): if n < len(pfs): return pfs[n] else: if n in setprimes: return {n : 1} ans = {} for p in primes:
from helpers import prime_factorizations pfs = prime_factorizations(1000) def pf_divisors(pf): if len(pf) == 0: yield 1 return prime, power = pf.popitem() for divisor in pf_divisors(pf): for i in range(power + 1): yield divisor * prime**i pf[prime] = power def divisors(n): pf = pfs[n] for i in pf_divisors(pf): yield i def proper_divisors(n): for divisor in divisors(n): if divisor != n: yield divisor def smallest_number_not_in_set(s): i = 0 while i in s: i += 1 return i
from helpers import sieve, prime_factorizations from collections import defaultdict limit = 10**6 * 40 primes = sieve(limit) setprimes = set(primes) small_prime_factorizations = prime_factorizations(limit / 40) small_totient_chain_length = [0] def euler_phi(prime_factorization): answer = 1 for (prime, power) in prime_factorization.items(): answer *= prime - 1 answer *= prime**(power - 1) return answer def compute_chain_length(i): if i == 1: return 1 prime_factorization = small_prime_factorizations[i] phi_i = euler_phi(prime_factorization) return 1 + small_totient_chain_length[phi_i] def get_chain_length(n): if n < len(small_totient_chain_length): return small_totient_chain_length[n] else: prime_factorization = defaultdict(lambda : 0) for prime in primes:
from helpers import sieve_euler_phi, crt, gcd, prime_factorizations upper_limit = 10**6 + 5000 lower_limit = 10**6 print crt([(1, 2), (2, 3), (3, 5)]) euler_phi = sieve_euler_phi(upper_limit + 1) pfs = prime_factorizations(upper_limit + 1) def attempt_to_solve(a, n, b, m): d = gcd(n, m) reduced_a = a % d reduced_b = b % d if reduced_a != reduced_b: return 0 else: n_pf = pfs[n] m_pf = pfs[m] L = [] for (prime, power) in n_pf.items(): if prime in m_pf and m_pf[prime] >= power: # do nothing for now r = 1 else: L.append((a % (prime**power), prime**power)) for (prime, power) in m_pf.items(): if prime in n_pf and n_pf[prime] > power: # do nothing r = 1 else: L.append((b % (prime**power), prime**power))
from helpers import sieve_euler_phi, crt, gcd, prime_factorizations upper_limit = 10**6 + 5000 lower_limit = 10**6 print crt([(1, 2), (2, 3), (3, 5)]) euler_phi = sieve_euler_phi(upper_limit + 1) pfs = prime_factorizations(upper_limit + 1) def attempt_to_solve(a, n, b, m): d = gcd(n, m) reduced_a = a % d reduced_b = b % d if reduced_a != reduced_b: return 0 else: n_pf = pfs[n] m_pf = pfs[m] L = [] for (prime, power) in n_pf.items(): if prime in m_pf and m_pf[prime] >= power: # do nothing for now r = 1 else: L.append((a % (prime**power), prime**power)) for (prime, power) in m_pf.items(): if prime in n_pf and n_pf[prime] > power: # do nothing r = 1 else: L.append((b % (prime**power), prime**power))