Пример #1
0
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
Пример #2
0
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)
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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)
Пример #6
0
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
Пример #7
0
 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
Пример #8
0
 def is_prime(n):
     end = eulerlib.sqrt(n)
     for p in primes:
         if p > end:
             break
         if n % p == 0:
             return False
     return True
Пример #9
0
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
Пример #10
0
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
Пример #11
0
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
Пример #12
0
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
Пример #13
0
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
Пример #14
0
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
Пример #15
0
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
Пример #16
0
 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
Пример #17
0
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
Пример #18
0
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
Пример #19
0
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
Пример #20
0
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
Пример #21
0
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]
Пример #22
0
    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
Пример #23
0
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
Пример #24
0
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
Пример #25
0
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
Пример #26
0
 def is_prime_generating(n):
     return all((n % d != 0 or isprime[d + n // d])
                for d in range(2,
                               eulerlib.sqrt(n) + 1))
Пример #27
0
def test_sqrt(input_x, expected_output):
    output = eulerlib.sqrt(input_x)
    print(output)
    assert output == expected_output