问题23要求所有数字的总和“不是两个丰富的数字之和”。我们只需要检查小于28123的数字。如果其适当的除数总和大于n的整数,则整数n是丰富的。这是从1 + 2 + 3 + 4 + 6 = 16> 1开始的第一个数。 12.这使得24是最小的数字,它是2个丰富数字的总和,所以我们希望将它从总和中排除。
这是我的python代码,我尝试了许多变体,但使用相同的想法:
import math
def divisors_of(n):
divs=[1]
for i in range(2,int(math.sqrt(n))+1):
if i**2 == n:
divs.append(i)
elif n%i == 0:
divs.append(i)
divs.append(n//i)
return divs
def is_abun(n):
return sum(divisors_of(n))>n
numbers=[i for i in range(1,28123)]
for i in numbers:
for j in range(1,i):
if is_abun(j) and is_abun(i-j):
numbers.remove(i)
break
print(sum(numbers))
这个想法很简单,如果j和i-j是丰富的数字,那么当然j +(i-j)= i是大量数字的总和,所以我从我的数字列表中删除它。然后我总结所有剩余的数字。我不知道这怎么可能失败。然而,结果应该是(来自另一个来源)4179871,而我总是在197711987的球场得到一些东西,这个数字超过了47倍。
我真的无法理解这是如何无法生成正确的结果。必须有一些线路没有做我认为的那样,但这里的一切只是太简单让我对它们产生怀疑。我认为最可能的错误是计算丰富的数字,但我几乎完全确定该部分是正确的(如果我得到的代码是生成一个小于28123的丰富数字列表,我得到一个长度为6965的列表,这是多少数量少于28123 WolframAlpha声称的数字。
答案 0 :(得分:3)
问题是您在迭代时修改列表numbers
。这样可以减少您预期的数量。
你应该迭代它的一个副本:
for i in list(numbers):
for j in range(1,i):
if is_abun(j) and is_abun(i-j):
numbers.remove(i)
break
要了解正在发生的事情,请考虑以下事项:
>>> numbers = list(range(10))
>>> for i in numbers:
... if i%2 == 0:
... numbers.remove(i)
... print(i)
...
0
2
4
6
8
正如您所看到的,for
循环仅迭代偶数。那是因为上面的for
循环大致等同于以下内容:
i = 0
while i < len(numbers):
number = numbers[i]
if number % 2 == 0:
numbers.remove(number)
print(number)
i += 1
因此,当您第一次拥有i = 0
并因此number = 0
时,您会从0
移除numbers
,所以现在您拥有numbers = [1,2,3,4,..., 9]
。请注意值1
最终位于0
的位置,所以下一次迭代我们有i = 1
和numbers[1] == [1,2,3,4,...,9][1] == 2
所以我们跳过了数字1
!
每次删除号码时,列表都会被修改,如果此修改导致项目向左移动,则实际上是在跳过它们。这就是你想迭代列表的副本的原因:这样对原始列表的修改不会影响迭代期间“产生”的数字。