Files
euler/python/e710.py
T
2026-07-04 12:22:22 -04:00

96 lines
2.2 KiB
Python

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