def problem146(): LIMIT = 150000000 INCREMENTS = [1, 3, 7, 9, 13, 27] # Must be in non-decreasing order NON_INCREMENTS = set(range(INCREMENTS[-1])) - set(INCREMENTS) maxnumber = LIMIT ** 2 + INCREMENTS[-1] primes = eulerlib.list_primes(eulerlib.sqrt(maxnumber)) def has_consecutive_primes(n): # Generate the set of numbers to test for primality n2 = n ** 2 temp = [(n2 + k) for k in INCREMENTS] # Test that each number is prime. # Note: The nesting of the loops can be reversed, but this way is much faster. if any((x != p and x % p == 0) for p in primes for x in temp): return False # Test that each number that is not an increment is composite. # This checks that the prime numbers we found are in fact consecutive. return all((not is_prime(n2 + k)) for k in NON_INCREMENTS) def is_prime(n): end = eulerlib.sqrt(n) for p in primes: if p > end: break if n % p == 0: return False return True ans = sum(n for n in range(0, LIMIT, 10) if has_consecutive_primes(n)) return ans
def problem171(): LENGTH = 20 BASE = 10 MODULUS = 10**9 # Maximum possible squared digit sum (for 99...99) MAX_SQR_DIGIT_SUM = (BASE - 1)**2 * LENGTH # sqsum[n][s] is the sum of all length-n numbers with a square digit sum of s, modulo MODULUS # count[n][s] is the count of all length-n numbers with a square digit sum of s, modulo MODULUS sqsum = [] count = [] for i in range(LENGTH + 1): sqsum.append([0] * (MAX_SQR_DIGIT_SUM + 1)) count.append([0] * (MAX_SQR_DIGIT_SUM + 1)) if i == 0: count[0][0] = 1 else: for j in range(BASE): for k in itertools.count(): index = k + j**2 if index > MAX_SQR_DIGIT_SUM: break sqsum[i][index] = (sqsum[i][index] + sqsum[i - 1][k] + pow( BASE, i - 1, MODULUS) * j * count[i - 1][k]) % MODULUS count[i][index] = (count[i][index] + count[i - 1][k]) % MODULUS ans = sum(sqsum[LENGTH][i**2] for i in range(1, eulerlib.sqrt(MAX_SQR_DIGIT_SUM))) return "{:09d}".format(ans % MODULUS)
def problem111(): DIGITS = 10 primes = eulerlib.list_primes(eulerlib.sqrt(10**DIGITS)) # Only valid if 1 < n <= 10^DIGITS. def is_prime(n): end = eulerlib.sqrt(n) for p in primes: if p > end: break if n % p == 0: return False return True ans = 0 # For each repeating digit for digit in range(10): # Search by the number of repetitions in decreasing order for rep in range(DIGITS, -1, -1): sum = 0 digits = [0] * DIGITS # Try all possibilities for filling the non-repeating digits for i in range(9**(DIGITS - rep)): # Build initial array. For example, if DIGITS=7, digit=5, rep=4, i=123, then the array will be filled with 5,5,5,5,1,4,7. for j in range(rep): digits[j] = digit temp = i for j in range(DIGITS - rep): d = temp % 9 if d >= digit: # Skip the repeating digit d += 1 if ( j > 0 and d > digits[DIGITS - j] ): # If this is true, then after sorting, the array will be in an already-tried configuration break digits[-1 - j] = d temp //= 9 else: digits.sort() # Start at lowest permutation while True: # Go through all permutations if ( digits[0] > 0 ): # Skip if the number has a leading zero, which means it has less than DIGIT digits num = int("".join(map(str, digits))) if is_prime(num): sum += num if not eulerlib.next_permutation(digits): break if sum > 0: # Primes found; skip all lesser repetitions ans += sum break return ans
def problem304(): BASE = 10 ** 14 SEARCH_RANGE = ( 10000000 ) # Number of candidates starting from BASE to search for primes. Hopefully there are 100 000 primes among here. MODULUS = 1234567891011 # iscomposite[i] pertains to the number BASE + i # Sieve of Eratosthenes, but starting at BASE iscomposite = [False] * SEARCH_RANGE primes = eulerlib.list_primes(eulerlib.sqrt(BASE + SEARCH_RANGE)) for p in primes: for i in range((BASE + p - 1) // p * p - BASE, len(iscomposite), p): iscomposite[i] = True # Returns p - BASE, where p is the next prime after n + BASE def next_prime(n): while True: n += 1 if n >= len(iscomposite): raise AssertionError("Search range exhausted") if not iscomposite[n]: return n ans = 0 p = 0 for i in range(100000): p = next_prime(p) ans = (ans + fibonacci_mod(BASE + p, MODULUS)) % MODULUS return ans
def problem087(): """ The smallest number expressible as the sum of a prime square, prime cube, and prime fourth power is 28. In fact, there are exactly four numbers below fifty that can be expressed in such a way: 28 = 2^2 + 2^3 + 2^4 33 = 3^2 + 2^3 + 2^4 49 = 5^2 + 2^3 + 2^4 47 = 2^2 + 3^3 + 2^4 How many numbers below fifty million can be expressed as the sum of a prime square, prime cube, and prime fourth power? """ limit = 50000000 primes = eulerlib.list_primes(eulerlib.sqrt(limit)) sums = {0} for i in range(2, 5): newsums = set() for p in primes: q = p**i if q > limit: break for x in sums: if x + q <= limit: newsums.add(x + q) sums = newsums return len(sums)
def list_sigma2(n): # If i has a prime factor p <= sqrt, then quasiprimefactor[i] = p. # Otherwise i > sqrt must be prime, and quasiprimefactor[i] = 0 because i may overflow an int16. sqrt = eulerlib.sqrt(n) quasiprimefactor = array.array("H", (0 for _ in range(n + 1))) # Richer version of the sieve of Eratosthenes for i in range(2, sqrt + 1): if quasiprimefactor[i] == 0: quasiprimefactor[i] = i for j in range(i * i, n + 1, i): if quasiprimefactor[j] == 0: quasiprimefactor[j] = i if sys.version_info.major < 3: sigma2 = [0] * (n + 1) else: sigma2 = array.array("Q", (0 for _ in range(n + 1))) sigma2[1] = 1 for i in range(2, len(sigma2)): p = quasiprimefactor[i] if p == 0: p = i sum = 1 j = i p2 = p * p k = p2 while j % p == 0: sum += k j //= p k *= p2 sigma2[i] = sum * sigma2[j] return sigma2
def floor(self): temp = eulerlib.sqrt(self.b * self.b * self.d) if self.b < 0: temp = -(temp + 1) temp += self.a if temp < 0: temp -= self.c - 1 return temp // self.c
def is_prime(n): end = eulerlib.sqrt(n) for p in primes: if p > end: break if n % p == 0: return False return True
def totient(n): assert n > 0 p = 1 i = 2 end = eulerlib.sqrt(n) while i <= end: if n % i == 0: # Found a factor p *= i - 1 n //= i while n % i == 0: p *= i n //= i end = eulerlib.sqrt(n) i += 1 if n != 1: p *= n - 1 return p
def count_divisors_squared(n): count = 1 end = eulerlib.sqrt(n) for i in itertools.count(2): if i > end: break if n % i == 0: j = 0 while True: n //= i j += 1 if n % i != 0: break count *= j * 2 + 1 end = eulerlib.sqrt(n) if n != 1: # Remaining largest prime factor count *= 3 return count
def smallest_prime_factor(n): """ :param n: :return: the smallest factor of n, which is in the range [2, n]. The result is always prime. """ assert n >= 2 for i in range(2, eulerlib.sqrt(n) + 1): if n % i == 0: return i return n # n itself is prime
def num_divisors(input_n): """ :param input_n: :return: """ end = eulerlib.sqrt(input_n) result = sum(2 for i in range(1, end + 1) if input_n % i == 0) if end**2 == input_n: result -= 1 return result
def problem187(): LIMIT = 10**8 - 1 ans = 0 primes = eulerlib.list_primes(LIMIT // 2) sqrt = eulerlib.sqrt(LIMIT) for (i, p) in enumerate(primes): if p > sqrt: break end = binary_search(primes, LIMIT // p) ans += (end + 1 if end >= 0 else -end - 1) - i return ans
def count_distinct_prime_factors(n): count = 0 while n > 1: count += 1 for i in range(2, eulerlib.sqrt(n) + 1): if n % i == 0: while True: n //= i if n % i != 0: break break else: break # n is prime return count
def problem142(): # Finds any summation s = x+y+z such that s < limit, 0 < z < y < x, and these are # perfect squares: x+y, x-y, x+z, x-z, y+z, y-z. Returns -1 if none is found. # Suppose we let x + y = a^2 and x - y = b^2, so that they are always square. # Then x = (a^2 + b^2) / 2 and y = (a^2 - b^2) / 2. By ensuring a > b > 0, we have x > y > 0. # Now z < y and z < limit - x - y. Let y + z = c^2, then explicitly check # if x+z, x-z, and y-z are square. def find_sum(limit): for a in itertools.count(1): if a * a >= limit: break for b in reversed(range(1, a)): if ( a + b ) % 2 != 0: # Need them to be both odd or both even so that we get integers for x and y continue x = (a * a + b * b) // 2 y = (a * a - b * b) // 2 if x + y + 1 >= limit: # Because z >= 1 continue zlimit = min(y, limit - x - y) for c in itertools.count(eulerlib.sqrt(y) + 1): z = c * c - y if z >= zlimit: break if issquare[x + z] and issquare[x - z] and issquare[y - z]: return x + y + z return None sumlimit = 10 # Raise the limit until a summation is found while True: issquare = [False] * sumlimit for i in range(eulerlib.sqrt(len(issquare) - 1) + 1): issquare[i * i] = True summation = find_sum(sumlimit) if summation is not None: break sumlimit *= 10 # Lower the limit until now summation is found while True: summation = find_sum(sumlimit) if summation is None: # No smaller summation found return sumlimit sumlimit = summation
def is_prime(x): if x < 0: raise ValueError() elif x in (0, 1): return False else: end = eulerlib.sqrt(x) for p in primes: if p > end: break if x % p == 0: return False for i in range(primes[-1] + 2, end + 1, 2): if x % i == 0: return False return True
def problem347(): """ The largest integer ≤ 100 that is only divisible by both the primes 2 and 3 is 96, as 96=32*3=2^5*3.For two distinct primes p and q let M(p,q,N) be the largest positive integer ≤N only divisibleby both p and q and M(p,q,N)=0 if such a positive integer does not exist. E.g. M(2,3,100)=96. M(3,5,100)=75 and not 90 because 90 is divisible by 2 ,3 and 5. Also M(2,73,100)=0 because there does not exist a positive integer ≤ 100 that is divisible by both 2 and 73. Let S(N) be the sum of all distinct M(p,q,N).S(100)=2262. Find S(10 000 000). """ limit = 10000000 possible = set() primes = eulerlib.list_primes(limit // 2) end = eulerlib.sqrt(limit) for i in range(len(primes)): p = primes[i] if p > end: break for j in range(i + 1, len(primes)): q = primes[j] lcm = p * q if lcm > limit: break multlimit = limit // lcm multiplier = 1 while multiplier * p <= multlimit: multiplier *= p maxmult = multiplier while multiplier % p == 0: multiplier //= p while multiplier * q <= multlimit: multiplier *= q maxmult = max(multiplier, maxmult) possible.add(maxmult * lcm) ans = sum(possible) return ans
def problem075(): """ It turns out that 12 cm is the smallest length of wire that can be bent to form an integer sided right angle triangle in exactly one way, but there are many more examples. 12 cm: (3,4,5) 24 cm: (6,8,10) 30 cm: (5,12,13) 36 cm: (9,12,15) 40 cm: (8,15,17) 48 cm: (12,16,20) In contrast, some lengths of wire, like 20 cm, cannot be bent to form an integer sided right angle triangle, and other lengths allow more than one solution to be found; for example, using 120 cm it is possible to form exactly three different integer sided right angle triangles. 120 cm: (30,40,50), (20,48,52), (24,45,51) Given that L is the length of the wire, for how many values of L ≤ 1,500,000 can exactly one integer sided right angle triangle be formed? """ LIMIT = 1500000 # Pythagorean triples theorem: # Every primitive Pythagorean triple with a odd and b even can be expressed as # a = st, b = (s^2-t^2)/2, c = (s^2+t^2)/2, where s > t > 0 are coprime odd integers. # triples = set() for s in range(3, eulerlib.sqrt(LIMIT) + 1, 2): for t in range(s - 2, 0, -2): if math.gcd(s, t) == 1: a = s * t b = (s * s - t * t) // 2 c = (s * s + t * t) // 2 if a + b + c <= LIMIT: triples.add((a, b, c)) ways = [0] * (LIMIT + 1) for triple in triples: sigma = sum(triple) for i in range(sigma, len(ways), sigma): ways[i] += 1 ans = ways.count(1) return ans
def problem401(): LIMIT = 10**15 MODULUS = 10**9 # Can be any number from 1 to LIMIT, but somewhere near sqrt(LIMIT) is preferred splitcount = eulerlib.sqrt(LIMIT) # Consider divisors individually up and including this number splitat = LIMIT // (splitcount + 1) # The sum (s+1)^2 + (s+2)^2 + ... + (e-1)^2 + e^2. def sum_squares(s, e): return (e * (e + 1) * (e * 2 + 1) - s * (s + 1) * (s * 2 + 1)) // 6 ans = sum((i * i * (LIMIT // i)) for i in range(1, splitat + 1)) ans += sum((sum_squares(LIMIT // (i + 1), LIMIT // i) * i) for i in range(1, splitcount + 1)) return ans % MODULUS
def problem203(): # Collect unique numbers in Pascal's triangle numbers = set(eulerlib.binomial(n, k) for n in range(51) for k in range(n + 1)) maximum = max(numbers) # Prepare list of squared primes primes = eulerlib.list_primes(eulerlib.sqrt(maximum)) primessquared = [p * p for p in primes] def is_squarefree(n): for p2 in primessquared: if p2 > n: break if n % p2 == 0: return False return True # Sum up the squarefree numbers ans = sum(n for n in numbers if is_squarefree(n)) return ans
def problem085(): """ By counting carefully it can be seen that a rectangular grid measuring 3 by 2 contains eighteen rectangles: Although there exists no rectangular grid that contains exactly two million rectangles, find the area of the grid with the nearest solution. p_085.gif """ target = 2000000 end = eulerlib.sqrt(target) + 1 gen = ((w, h) for w in range(1, end) for h in range(1, end)) def func(wh): return abs(num_rectangles(*wh) - target) ans = min(gen, key=func) return ans[0] * ans[1]
def find_sum(limit): for a in itertools.count(1): if a * a >= limit: break for b in reversed(range(1, a)): if ( a + b ) % 2 != 0: # Need them to be both odd or both even so that we get integers for x and y continue x = (a * a + b * b) // 2 y = (a * a - b * b) // 2 if x + y + 1 >= limit: # Because z >= 1 continue zlimit = min(y, limit - x - y) for c in itertools.count(eulerlib.sqrt(y) + 1): z = c * c - y if z >= zlimit: break if issquare[x + z] and issquare[x - z] and issquare[y - z]: return x + y + z return None
def problem100(): """ If a box contains twenty-one coloured discs, composed of fifteen blue discs and six red discs, and two discs were taken at random, it can be seen that the probability of taking two blue discs, P(BB) = (15/21)×(14/20) = 1/2. The next such arrangement, for which there is exactly 50% chance of taking two blue discs at random, is a box containing eighty-five blue discs and thirty-five red discs. By finding the first arrangement to contain over 10^12 = 1,000,000,000,000 discs in total, determine the number of blue discs that the box would contain. """ # Fundamental solution x0 = 3 y0 = 1 # Current solution x = x0 y = y0 # An alias for the number of red discs while True: # Check if this solution is acceptable sqrt = eulerlib.sqrt(y**2 * 8 + 1) if sqrt % 2 == 1: # Is odd blue = (sqrt + 1) // 2 + y if blue + y > 10**12: return blue # Create the next bigger solution nextx = x * x0 + y * y0 * 8 nexty = x * y0 + y * x0 x = nextx y = nexty
def try_search(limit): # If i can be expressed as the sum of a square greater than 1 and # a cube greater than 1, then ways[i] is the number of different ways # it can be done. Otherwise, i is not a key in the ways dictionary. ways = {} for i in itertools.count(2): cube = i**3 if cube >= limit: break for j in range(2, eulerlib.sqrt(limit - 1 - cube) + 1): index = cube + j**2 ways[index] = ways.get(index, 0) + 1 result = 0 count = 0 for i in sorted(ways.keys()): if ways[i] == TARGET_WAYS and is_palindrome(i): result += i count += 1 if count == TARGET_COUNT: return result return None
def problem451(): """ Consider the number 15. There are eight positive numbers less than 15 which are coprime to 15: 1, 2, 4, 7, 8, 11, 13, 14. The modular inverses of these numbers modulo 15 are: 1, 8, 4, 13, 2, 11, 7, 14 because 1*1 mod 15=1 2*8=16 mod 15=1 4*4=16 mod 15=1 7*13=91 mod 15=1 11*11=121 mod 15=1 14*14=196 mod 15=1 Let I(n) be the largest positive number m smaller than n-1 such that the modular inverse of m modulo n equals m itself. So I(15)=11. Also I(100)=51 and I(7)=1. Find ∑I(n) for 3≤n≤2·10^7 """ LIMIT = 20000000 # Build table of smallest prime factors smallestprimefactor = array.array("L", itertools.repeat(0, LIMIT + 1)) end = eulerlib.sqrt(len(smallestprimefactor) - 1) for i in range(2, len(smallestprimefactor)): if smallestprimefactor[i] == 0: smallestprimefactor[i] = i if i <= end: for j in range(i * i, len(smallestprimefactor), i): if smallestprimefactor[j] == 0: smallestprimefactor[j] = i # Returns all the solutions (in ascending order) such that # for each k, 1 <= k < n and k^2 = 1 mod n. def get_solutions(n): if smallestprimefactor[n] == n: # n is prime return (1, n - 1) else: temp = [] p = smallestprimefactor[n] sols = solutions[n // p] for i in range(0, n, n // p): for j in sols: k = i + j if k * k % n == 1: temp.append(k) return tuple(temp) # Process every integer in range solutions = [(), (), (1, )] ans = 0 for i in range(3, LIMIT + 1): sols = get_solutions(i) if i <= LIMIT // 2: solutions.append(sols) ans += sols[-2] # Second-largest solution return ans
def is_prime_generating(n): return all((n % d != 0 or isprime[d + n // d]) for d in range(2, eulerlib.sqrt(n) + 1))
def test_sqrt(input_x, expected_output): output = eulerlib.sqrt(input_x) print(output) assert output == expected_output