我为Project Euler #12编写了此代码。它非常慢(或不起作用),我发现另一个非常相似的代码并立即得到答案。 我的代码:
import math
def get_triangular(nth):
return sum(range(1,nth+1))
def get_divisors_count(n):
divisors = 0
for a in range(1,math.ceil(n/2)+1):
if n%a == 0:
divisors += 1
return divisors
a = 1
while(True):
if get_divisors_count(get_triangular(a)) > 500:
print(a)
a += 1
我在Stack Overflow上找到的代码:
import math
def main():
l = []
one = 0
a = 1
b = 2
while one == 0:
a = a + b
b += 1
l = []
sqrt_a = int(math.sqrt(a))
for x in range(1, sqrt_a + 1):
if a % x == 0:
l.append(x)
if x < math.sqrt(a):
l.append(a // x)
if len(l) > 500:
# print(a)
one = 1
print(a, b, len(l))
if __name__ == '__main__':
main()
答案 0 :(得分:3)
首先,你的程序永远不会结束。你有一个没有while True
的{{1}}循环,或任何其他退出循环的方法。您发布的其他代码包含break
而不是while one == 0
,并且只要while True
设置one = 1
。这有点尴尬,但它确实有效。
所以:
len(l) > 500
这仍然很慢,但不是无限慢。
下一个最大的区别是你计算到n / 2 + 1,而另一个代码计数到sqrt(n),并计算每个除数两次。 (为什么这样做?想一想:如果a = 1
while(True):
if get_divisors_count(get_triangular(a)) > 500:
print(a)
break
a += 1
是[{1}}的除数,那么a
也是如此,其中只有一个必须小于n
除非他们都等于它。)
你也在其他程序没有的一些领域浪费了一些时间,比如反复计算n/a
,而不是保持一个运行总和并做sqrt(n)
。另一方面,你已经节省了一些时间,只需保留一个除数,而不是建立一个列表然后再取其长度。
但与之前的问题相比,这些都是微不足道的。至少您的程序现在具有相同的算法复杂度sum(range(1, nth+1))
,而不是running_sum += a
(或无限);在我的机器上,它在15.3秒内比12.1运行。
如果你真的想让它更快,有两个主要选择: