Exemplo n.º 1
0
def smallest_collatz(seq, L):
    '''Return the smallest starting number > L for the modified Collatz sequence starting with
    the encoded move sequence seq.''' 
    r, two_k, n3 = 0L, 1L, pow(3L, len(seq))
    # The reverse Collatz sequence has the form b_n = (3*n b_0 + r_n)/2^(k_n). r_n, 2^(k_n) admit an
    # easy recurrence relationship vs. r_(n-1), 2^(k_(n-1)).
    for move in reversed(seq):
        if move == 'D': r *= 3
        elif move == 'U': r, two_k = 3 * r - 2 * two_k, 4 * two_k
        elif move == 'd': r, two_k = 3 * r + two_k, 2 * two_k
    # Use the Chinese remainder theorem to derive the form b_n = 3^n x + a*r where a = multiplicative
    # inverse of 2^(k_n) mod 3^n. a is efficiently found using the extended Euclid algorithm. Convert
    # this to b_n = 3^n + R where 0 <= R < 3^n.
    R = extended_gcd(two_k, n3)[0] * r % n3
    return n3 * int_ceil((L + 1. - R) / n3) + R
Exemplo n.º 2
0
For a prime p let S(p) = (SUM (p-k)!) mod(p) for 1 <= k <= 5.

For example, if p=7,
(7-1)! + (7-2)! + (7-3)! + (7-4)! + (7-5)! = 6! + 5! + 4! + 3! + 2! = 720+120+24+6+2 = 872.
As 872 mod(7) = 4, S(7) = 4.

It can be verified that SUM S(p) = 480 for 5 <= p < 100.

Find SUM S(p) for 5 <= p < 108.
============================================================
'''
from itertools import islice, imap
from problem007 import primes
from problem134 import extended_gcd

inv_mod = lambda x, p: extended_gcd(x, p)[0]
sum_S = lambda N, k: sum(S(p, k) for p in imap(long, primes('lt', N)) if p >= k)
S = lambda p, k: reduce(lambda x, y: (x + y) % p, islice(p_minus_k_factorial_mod(p), k - 2))

def p_minus_k_factorial_mod(p):
    pk, x = p - 2, 1
    while True:
        x *= inv_mod(pk, p)
        yield x
        pk -= 1

if __name__ == "__main__":
    print S(7, 5)  # 4
    print sum_S(10 ** 2, 5)  # 480
    print sum_S(10 ** 8, 5)  # 139602943319822