【发布时间】:2011-02-03 03:34:31
【问题描述】:
我正在尝试解决this Project Euler question:
一个完美数是一个数,它的真因数之和 正好等于数字。例如,适当的总和 28 的除数将是 1 + 2 + 4 + 7 + 14 = 28,这意味着 28 是一个完美的数字。
如果一个数 n 的真因数之和为 小于n,如果这个总和超过n,则称为丰富。
因为 12 是最小的丰度数,1 + 2 + 3 + 4 + 6 = 16,所以 可以写成两个丰富数之和的最小数 是 24。通过数学分析,可以证明所有的整数 大于 28123 可以写成两个丰富数之和。 然而,这个上限不能通过分析进一步降低 即使已知最大的数是不可能的 表示为两个丰富数之和小于此限制。
求所有不能写成的正整数之和 两个丰富数之和。
我的解决方案:
#returns a list of the divisors of a given number
def Divs(Number):
Divisors = []
for i in range(2 , int(Number**0.5) + 1):
if Number % i == 0:
Divisors.append(i)
for q in range(len(Divisors)):
if Divisors[q] != (Number / Divisors[q]):
Divisors.append(Number / Divisors[q])
Divisors.insert(0,1)
return Divisors
#returns a list of abundant numbers up to and including the limit
def AbList(limit):
Abundant = []
for i in range(11,limit + 1):
if sum(Divs(i)) > i:
Abundant.append(i)
return Abundant
#Finds the sum of all positive integers that cannot be written as the
#sum of two abundant numbers...
def AbSum(limit):
Abundant = AbList(limit)
NoAbSum = 0
for i in range(1 , limit):
AbSum = 0
x = 0
for x in Abundant:
if i - x in Abundant[:i]:
AbSum = 1
break
if AbSum == 0:
NoAbSum += i
return NoAbSum
我的 3.4 GhZ 处理器花了大约 15 分钟来解决这个问题,我正在寻找更好的方法。我不关心前两个函数,因为它们一起运行不到一秒钟。第三个功能是这里的踢球者。它遍历数字范围直到极限(在本例中为 20000 左右),并且每次都遍历丰富数字列表,从当前数字中减去每个,然后根据丰富列表检查该答案数字。如果匹配,则循环中断并再次尝试下一个数字,一直到限制。
我知道必须有更好的方法来做到这一点,但我对编程有点陌生。我怎样才能加快这个算法?
【问题讨论】:
-
你当前的解决方案是
O(m * n),其中m(极限)远大于n(低于极限的丰富数)。现在,计算所有是其他丰富数之和的数字的时间复杂度是多少?这比您当前的解决方案更好还是更差? -
为什么要对除数进行排序?
-
一旦您提交了正确的解决方案,您就可以访问该问题的讨论线程,在那里您会找到一些最有效的解决方案。
-
S. Lott,出于某种原因,我懒洋洋地在末尾添加了 1。修好了,谢谢。 kefeizhou,我通读了讨论线程,在那里我看到了很多解决方案,但很少有解释。先进的、优化的解决方案对我来说都非常难以理解……:/
-
@crayZsaaron:这与问题没有直接关系,但是我觉得我应该提到您的代码中的一些小问题——比任何东西都更美观。首先,
AbSum()中的x = 0行不是必需的; x 在for语句中定义。其次,您可以(在python中)在for循环的末尾使用else语句,而不是使用本地AbSum变量来存储if i - x in Abundant[:i]:的结果,该语句在循环的末尾执行only 如果break没有被调用 - 即只有在没有找到匹配项时循环。
标签: python