📝 docs(0029.DistinctPowers):添加问题描述和解题思路文档 ✨ feat(euler_29.py):实现基础解决方案和高效算法 ✨ feat(euler_29_best.py):实现基于容斥原理的最优解决方案
93 lines
2.5 KiB
Python
93 lines
2.5 KiB
Python
"""
|
||
Consider all integer combinations of a^b for 2<=a<=5 and 2<=b<=5 :
|
||
|
||
2^2 = 4 2^3 = 8 2^4 = 16 2^5 = 32
|
||
3^2 = 9 3^3 = 27 3^4 = 81 3^5 = 243
|
||
4^2 = 16 4^3 = 64 4^4 = 256 4^5 = 1024
|
||
5^2 = 25 5^3 = 125 5^4 = 625 5^5 = 3125
|
||
|
||
If they are then placed in numerical order, with any repeats removed,
|
||
we get the following sequence of 15 distinct terms:
|
||
|
||
4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125
|
||
|
||
How many distinct terms are in the sequence generated by a^b for 2<=a<=100 and 2<=b<=100 ?
|
||
"""
|
||
|
||
import time
|
||
|
||
|
||
def timer(func):
|
||
def wrapper(*args, **kwargs):
|
||
start_time = time.time()
|
||
result = func(*args, **kwargs)
|
||
end_time = time.time()
|
||
print(f"{func.__name__} runtime: {end_time - start_time} seconds")
|
||
return result
|
||
|
||
return wrapper
|
||
|
||
|
||
def count_distinct_terms_efficient(limit_a, limit_b):
|
||
# 预计算每个 a 的最小底数表示
|
||
base_map = {}
|
||
power_map = {}
|
||
|
||
for a in range(2, limit_a + 1):
|
||
base_map[a] = a
|
||
power_map[a] = 1
|
||
|
||
# 找出所有可以表示为幂的数
|
||
for power in range(2, 7): # 2^7=128>100,所以最多到6次幂
|
||
base = 2
|
||
while base**power <= limit_a:
|
||
value = base**power
|
||
# 如果这个值还没有被更小的底数表示
|
||
if base_map[value] == value:
|
||
base_map[value] = base
|
||
power_map[value] = power
|
||
base += 1
|
||
|
||
# 使用集合存储 (base, exponent) 对
|
||
seen = set()
|
||
|
||
for a in range(2, limit_a + 1):
|
||
base = base_map[a]
|
||
power = power_map[a]
|
||
|
||
# 如果 a 是某个数的幂,我们需要检查 base 是否还能分解
|
||
# 例如:16 = 4^2,但 4 = 2^2,所以 16 = 2^4
|
||
# 我们需要找到最终的 base
|
||
while base_map[base] != base:
|
||
power = power * power_map[base]
|
||
base = base_map[base]
|
||
|
||
for b in range(2, limit_b + 1):
|
||
seen.add((base, power * b))
|
||
|
||
return len(seen)
|
||
|
||
|
||
def do_compute(a_top: int, b_top: int, a_down: int = 2, b_down: int = 2) -> int:
|
||
tmp = set()
|
||
for a in range(a_down, a_top + 1):
|
||
for b in range(b_down, b_top + 1):
|
||
tmp.add(a**b)
|
||
return len(tmp)
|
||
|
||
|
||
@timer
|
||
def main():
|
||
"""not bad"""
|
||
print(count_distinct_terms_efficient(100, 100))
|
||
|
||
|
||
@timer
|
||
def main2():
|
||
print(do_compute(100, 100))
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
main2()
|