项目欧拉#5的问题是: 2520是可以除以1到10中的每个数字而没有任何余数的最小数字。 可以被1到20的所有数字整除的最小正数是多少?
result=1
done=False
while not done:
result+=1
for x in range(2,21):
if result%x!=0:
break
elif x==20:
done=True
print(result)
但运行时需要很长时间。好吧,似乎这段代码不起作用。这段代码有什么问题?
答案 0 :(得分:1)
您正在寻找的是数字1到20中被称为“最不常见的多个"或者LCM”的内容。这是多个数字的结合这些数字的主要因素。例如,12和15的最小公倍数是多组{2,2,3}和{3,5}的并集,即{2,2,3,5}或60。
如果你有GCD功能("最大公约数"),那么你可以利用LCM(x,y)= x * y // GCD(x,y)的事实。然后,您可以从1开始累积LCM,并依次添加每个数字的唯一因子。
如果你正在使用Python 3,那么你可以从math.gcd
获得GCD。例如,以下将给出1到10的答案:
import math
r = 1
for i in range(2, 11):
r = r * i // math.gcd(r, i)
print(r)
这会按预期提供2520
。对于1到20,只需:
import math
r = 1
for i in range(2, 21):
r = r * i // math.gcd(r, i)
print(r)
这会给232792560
。
两种计算基本上都是即时的。
更新:你可以通过用以下代码替换循环体来实际挤出更多的东西:
r *= i // math.gcd(r, i)
这是有效的,因为i
是math.gcd(r, i)
的倍数。通过在乘法之前进行除法,计算中涉及的数字会略小一些。
答案 1 :(得分:0)
因为它必须除以20
,因此您只能检查20
的倍数 - 这样您就必须检查更少的数字。
如果数字除以20
,则必须除以2
,10
(20=2*10
),4
,5
(20=4*5
),因此您无需检查2
,4
,5
,10
。同样可以消除其他数字。
最后我得到了列表20
,19
,18
,17
,16
,15
,14
,{ {1}},13
11
结果:
import time
start = time.time()
result = 0
done = False
while not done:
result += 20
for x in [20, 19, 18, 17, 16, 15, 14, 13, 11]:
if result % x != 0:
break
else:
done = True
end = time.time()
print('result:', result)
print('time in seconds:', end-start)