diff --git a/python/e710.py b/python/e710.py new file mode 100644 index 0000000..59036af --- /dev/null +++ b/python/e710.py @@ -0,0 +1,95 @@ +MOD = 10**7 +SPACE = 10**7 +CACHE = [None for _ in range(SPACE * 2)] +CACHE_TILL = [None for _ in range(SPACE)] +CACHE_TILL_IS_TWO_EVEN = [None for _ in range(SPACE)] +CACHE_TILL_IS_TWO_ODD = [None for _ in range(SPACE)] +CACHE_T_FROM_ACC = [None for _ in range(SPACE * 2)] + + +def t_from_acc(rem: int, is_two: bool) -> int: + offset = rem + SPACE * is_two + if (value := CACHE_T_FROM_ACC[offset]) is not None: + return value + if rem < 0: + return 0 + s = t_from(rem, is_two) + t_from_acc(rem - 2, is_two) + s %= MOD + CACHE_T_FROM_ACC[offset] = s + return s + + +def t_from(rem: int, is_two: bool) -> int: + offset = rem + SPACE * is_two + if (value := CACHE[offset]) is not None: + return value + s = 0 + if rem < 0: + s = 0 + elif rem == 1: + s = 0 + elif rem == 0 and is_two: + s = 1 + else: + s += t_from(rem - 2, is_two) # d = 1 + s %= MOD + s += t_from(rem - 4, True) # d = 2 + s %= MOD + s += t_from_acc(rem - 6, is_two) + s %= MOD + # Naive (too slow): + # for d in range(1, rem // 2 + 1): + # s += t_from(rem - 2 * d, is_two or d == 2) + # s %= MOD + CACHE[offset] = s % MOD + return s % MOD + + +def t_old(n: int) -> int: + # print(f"t({n}) = ", end="") + s = 0 + for i in range(0, n + 1): + rem = n - i + s += t_from(rem, i == 2) + return s % MOD + + +def t(n: int) -> int: + s = CACHE_TILL[n - 4] + assert s is not None + s += t_from(n - 3, False) + CACHE_TILL[n - 3] = s % MOD + s += t_from(n - 2, True) + s %= MOD + s += t_from(n - 1, False) + s %= MOD + s += t_from(n, False) + s %= MOD + return s + + +def euler_710(): + for i in range(4): + CACHE_TILL[i] = 0 + + for n in range(4, 50): + t(n) + assert t(5) == 1 + assert t(6) == 4 + assert t(20) == 824 + assert t(42) == 1999923 + + for n in range(10, SPACE): + tn = t(n) + if tn % 10**6 == 0: + # print(f"t({n}) = {tn} <<<") + return n + # if tn % 10000 == 0: + # print(f"t({n}) = {tn}") + assert False, "Solution not found" + + +if __name__ == "__main__": + solution = euler_710() + print(f"e710.py: {solution}") + assert solution == 1275000