✨ feat(0043.SubStrDivisibility):添加欧拉项目第43题解决方案
📝 docs(0043.SubStrDivisibility):添加解题思路说明文档
This commit is contained in:
110
solutions/0043.SubStrDivisibility/euler_43.py
Normal file
110
solutions/0043.SubStrDivisibility/euler_43.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
"""
|
||||||
|
The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9
|
||||||
|
in some order, but it also has a rather interesting sub-string divisibility property.
|
||||||
|
|
||||||
|
Let d_1 be the 1st digit, d_2 be the 2nd digit, and so on. In this way, we note the following:
|
||||||
|
|
||||||
|
d_2d_3d_4 is divisible by 2
|
||||||
|
d_3d_4d_5 is divisible by 3
|
||||||
|
d_4d_5d_6 is divisible by 5
|
||||||
|
d_5d_6d_7 is divisible by 7
|
||||||
|
d_6d_7d_8 is divisible by 11
|
||||||
|
d_7d_8d_9 is divisible by 13
|
||||||
|
d_8d_9d_10 is divisible by 17
|
||||||
|
|
||||||
|
Find the sum of all 0 to 9 pandigital numbers with this property.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
from itertools import permutations
|
||||||
|
from tkinter.constants import TOP
|
||||||
|
|
||||||
|
|
||||||
|
def timer(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
start_time = time.perf_counter()
|
||||||
|
result = func(*args, **kwargs)
|
||||||
|
end_time = time.perf_counter()
|
||||||
|
print(f"Execution time: {end_time - start_time} seconds")
|
||||||
|
return result
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_numbers() -> list[int]:
|
||||||
|
ori = list(permutations(list(range(10))))
|
||||||
|
res = []
|
||||||
|
for x in ori:
|
||||||
|
if x[3] % 2 != 0:
|
||||||
|
continue
|
||||||
|
if x[5] not in [0, 5]:
|
||||||
|
continue
|
||||||
|
for i, d in enumerate([2, 3, 5, 7, 11, 13, 17]):
|
||||||
|
if int("".join(map(str, x[i + 1 : i + 4]))) % d != 0:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
res.append(int("".join(map(str, x))))
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def optimized_solve() -> tuple[int, list[int]]:
|
||||||
|
total = 0
|
||||||
|
|
||||||
|
# 从最后三位开始,这些必须能被17整除
|
||||||
|
candidates = []
|
||||||
|
for n in range(102, 1000, 17):
|
||||||
|
s = str(n).zfill(3)
|
||||||
|
if len(set(s)) == 3: # 三位数字必须不同
|
||||||
|
candidates.append(s)
|
||||||
|
|
||||||
|
# 逐步向前添加数字,检查约束
|
||||||
|
for i, prime in enumerate([13, 11, 7, 5, 3, 2]):
|
||||||
|
new_candidates = []
|
||||||
|
for cand in candidates:
|
||||||
|
# 获取当前已使用的数字
|
||||||
|
used_digits = set(cand)
|
||||||
|
|
||||||
|
# 尝试添加一个新数字在最前面
|
||||||
|
for d in "0123456789":
|
||||||
|
if d not in used_digits:
|
||||||
|
# 新形成的三位数
|
||||||
|
new_triplet = d + cand[:2]
|
||||||
|
# 检查是否能被对应的质数整除
|
||||||
|
if int(new_triplet) % prime == 0:
|
||||||
|
new_candidates.append(d + cand)
|
||||||
|
|
||||||
|
candidates = new_candidates
|
||||||
|
|
||||||
|
# 现在candidates中包含的是d_2到d_10(9位数字)
|
||||||
|
# 我们需要添加第一个数字d_1
|
||||||
|
final_numbers = []
|
||||||
|
for cand in candidates:
|
||||||
|
used_digits = set(cand)
|
||||||
|
# 找出缺失的那个数字
|
||||||
|
for d in "0123456789":
|
||||||
|
if d not in used_digits and d != "0": # d_1不能为0
|
||||||
|
num = d + cand
|
||||||
|
# 验证这是一个0-9的pandigital数
|
||||||
|
if len(set(num)) == 10:
|
||||||
|
final_numbers.append(num)
|
||||||
|
|
||||||
|
# 计算总和
|
||||||
|
total = sum(int(num) for num in final_numbers)
|
||||||
|
return total, [int(num) for num in final_numbers]
|
||||||
|
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def main():
|
||||||
|
numbers = get_all_numbers()
|
||||||
|
print(sum(numbers))
|
||||||
|
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def main_op():
|
||||||
|
total, _ = optimized_solve()
|
||||||
|
print(total)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
main_op()
|
||||||
8
solutions/0043.SubStrDivisibility/readme.md
Normal file
8
solutions/0043.SubStrDivisibility/readme.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# 简单思路说明
|
||||||
|
|
||||||
|
使用简单方式循环构建进行计算,刨除最简单的特征外,最多减少一半计算时间。这是从前往后进行计算的时候。
|
||||||
|
|
||||||
|
但是从后往前,就要快速多了。最后三位是形式确认的17的倍数,所以可以减少更多的计算次数,
|
||||||
|
(一千以内的17倍数只有不足60个),相应的递归到下一位数,所需计算次数也不会慢更多。
|
||||||
|
|
||||||
|
从最小可确认开始思考这种具有递归特征的问题,可能更容易进行计算求解。
|
||||||
Reference in New Issue
Block a user