✨ feat(euler_37.py):修复combine_lists函数处理空列表的情况,并改进输出格式显示每个截断素数
📝 docs(0037.TruncatablePrimes):添加readme.md文档解释截断素数只有11个的原因 ✨ feat(euler_38.py):新增全数字倍数问题的解决方案,包含优化算法和详细注释
This commit is contained in:
@@ -26,6 +26,8 @@ def timer(func):
|
|||||||
|
|
||||||
def combine_lists(a: list[int], b: list[int | None], c: list[int]) -> list[int]:
|
def combine_lists(a: list[int], b: list[int | None], c: list[int]) -> list[int]:
|
||||||
"""将三个列表的每个元素组合成数字"""
|
"""将三个列表的每个元素组合成数字"""
|
||||||
|
if b in [[],[None]] :
|
||||||
|
return [int(f"{x}{z}") for x, z in product(a, c)]
|
||||||
return [int(f"{x}{y}{z}") for x, y, z in product(a, b, c)]
|
return [int(f"{x}{y}{z}") for x, y, z in product(a, b, c)]
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +82,10 @@ def TruncatablePrime() -> list[int]:
|
|||||||
|
|
||||||
@timer
|
@timer
|
||||||
def main():
|
def main():
|
||||||
print(sum(TruncatablePrime()))
|
nums = TruncatablePrime()
|
||||||
|
for num in nums:
|
||||||
|
print(num)
|
||||||
|
print(f"Answer: {sum(nums)}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
23
solutions/0037.TruncatablePrimes/readme.md
Normal file
23
solutions/0037.TruncatablePrimes/readme.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# 截断素数
|
||||||
|
|
||||||
|
截断素数为什么只有11个?
|
||||||
|
我看到很多人有这个疑问,我自己也是思考了很久,才恍然的。
|
||||||
|
|
||||||
|
首先,向左向右分别截断一个素数,得到的依然是素数,这有多难呢?最右的数位显然只能是3、7。
|
||||||
|
2、5,会让这个向右截断的数编程可以合数,并且截断到最后只有一位数时,只能是2、3、5、7,在排除前面说的2和5,那么最右的数位只能是3、7。
|
||||||
|
相似的向左截断时,最左的数位显然只能是2、3、5、7。
|
||||||
|
中间的数,在向左截断时,显然不能时双数,那只能从1、3、5、7、9中选取,而5结尾的数必然可以被5整除,所以中间的数不能有5结尾。
|
||||||
|
这也就导致中间只有1、3、7、9这四个数可选。
|
||||||
|
到这我们了解了这个最基本的数字约束。
|
||||||
|
|
||||||
|
其次,由于截断的每一步都是一个素数,这就导致在高位数时可满足上述条件的素数会更为稀疏,
|
||||||
|
简单尝试验证就能发现,从7位数开始,满足上述约束的截断素数会更少,且不会超过6位数的情况,而6位数只有一个截断素数,739397。
|
||||||
|
由于素数的分布是高度不均匀的,所以,而偏向连续位数的素数出现概率本身就会随素数本身的不均匀分布而更难出现。
|
||||||
|
这也能很好的解释,为什么没有五位数的截断素数。
|
||||||
|
|
||||||
|
总之,需要严格证明的话,我们可以根据 [【Angell & Godwin,1977】](https://www.ams.org/journals/mcom/1977-31-137/S0025-5718-1977-0427213-2/S0025-5718-1977-0427213-2.pdf) 简单扩展得到,右截断素数在文章中以证明有83个,且最大的为73939133。那么,就可以简单枚举到这个最大的右截断素数中所有的左截断素数,就是结果了。
|
||||||
|
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
MiroMind的模型真的不错,很好的总结了截断素数相关的论文研究 [【分享链接】](https://dr.miromind.ai/share/e9e297da-7d1b-49d3-b4a9-bdae9249c9aa) 。
|
||||||
84
solutions/0038.PandigitalMultiples/euler_38.py
Normal file
84
solutions/0038.PandigitalMultiples/euler_38.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
"""
|
||||||
|
Take the number 192 and multiply it by each of 1, 2, and 3:
|
||||||
|
|
||||||
|
192 * 1 = 192
|
||||||
|
192 * 2 = 384
|
||||||
|
192 * 3 = 576
|
||||||
|
|
||||||
|
By concatenating each product we get the 1 to 9 pandigital, 192384576.
|
||||||
|
We will call 192384576 the concatenated product of 192 and (1,2,3).
|
||||||
|
|
||||||
|
The same can be achieved by starting with 9 and multiplying by 1,2,3,4, and 5,
|
||||||
|
giving the pandigital, 918273645, which is the concatenated product of 9 and (1,2,3,4,5).
|
||||||
|
|
||||||
|
What is the largest 1 to 9 pandigital 9-digit number that can be formed as the concatenated product
|
||||||
|
of an integer with (1,2,...,n) where n > 1?
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def timer(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
start_time = time.time()
|
||||||
|
result = func(*args, **kwargs)
|
||||||
|
end_time = time.time()
|
||||||
|
print(f"Execution time: {end_time - start_time:.6f} seconds")
|
||||||
|
return result
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
# def max_pandiMulti():
|
||||||
|
# max_num = 0
|
||||||
|
# key = [1,2,3,4,5]
|
||||||
|
# res = (0, [])
|
||||||
|
# ok = False
|
||||||
|
# for i in range(9999, 9, -1):
|
||||||
|
# mul_keys = [i * j for j in key]
|
||||||
|
# for j in range(5) :
|
||||||
|
# numx = "".join(map(str, mul_keys[:j+1]))
|
||||||
|
# if len(numx) == 9 and set(numx) == set('123456789'):
|
||||||
|
# max_num = max(max_num, int(numx))
|
||||||
|
# if max_num == int(numx):
|
||||||
|
# res = (i, key[:j+1])
|
||||||
|
# ok = True
|
||||||
|
# break
|
||||||
|
# if ok:
|
||||||
|
# break
|
||||||
|
# return max_num, res
|
||||||
|
|
||||||
|
|
||||||
|
def max_pandiMulti_better():
|
||||||
|
max_num = 0
|
||||||
|
res = (0, [])
|
||||||
|
# 配置列表:(n, start, end),其中 start > end,表示从大到小遍历
|
||||||
|
configs = [
|
||||||
|
(2, 9999, 5000), # n=2: i ∈ [5000, 9999]
|
||||||
|
(3, 333, 100), # n=3: i ∈ [100, 333]
|
||||||
|
(4, 33, 25), # n=4: i ∈ [25, 33]
|
||||||
|
(5, 9, 5) # n=5: i ∈ [5, 9]
|
||||||
|
]
|
||||||
|
|
||||||
|
for n, start, end in configs:
|
||||||
|
for i in range(start, end - 1, -1):
|
||||||
|
# 生成拼接字符串
|
||||||
|
s = ''.join(str(i * k) for k in range(1, n + 1))
|
||||||
|
# 检查是否为1-9 pandigital
|
||||||
|
if set(s) == set('123456789'):
|
||||||
|
num = int(s)
|
||||||
|
if num > max_num:
|
||||||
|
max_num = num
|
||||||
|
res = (i, list(range(1, n + 1)))
|
||||||
|
break # 当前n中,i递减,第一个满足条件的即为最大,可终止内层循环
|
||||||
|
|
||||||
|
return max_num, res
|
||||||
|
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def main():
|
||||||
|
maxnum, ress = max_pandiMulti_better()
|
||||||
|
print(f"{maxnum} : {ress}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user