欧拉计划#23-非丰富的总和

时间:2019-01-27 15:53:36

标签: python

这是任务:

  

问题23

     

一个完美数是一个数字,它的适当除数之和等于该数字。例如,适当除数28的总和就是1 + 2 + 4 + 7 + 14 = 28,这意味着28是一个完美的数。

     

如果数字n的适当除数之和小于n,则称n为不足;如果数字n的适当除数超过n,则称其为丰富。

     

由于12是最小的丰富数,所以1 + 2 + 3 + 4 + 6 = 16,可以写成两个丰富的数之和的最小数是24。通过数学分析,可以看出所有大于28123的整数可以写为两个丰富数字的总和。但是,即使知道无法表示为两个丰富数字之和的最大数字小于该上限,也无法通过分析进一步降低该上限。

     

找到所有不能写为两个丰富数字之和的正整数之和。

这是我的代码:

import time
import math
start = time.time()

abundant_num_list = []

def checkAbundant():

    for n in range(1, 28123):

        factor_sum = 0
        other_pair_factor = 0

        for i in range(2, int(n ** 0.5) + 1):
            if n % i == 0:         
                if math.floor(math.sqrt(n)) == math.sqrt(n):
                    other_pair_factor = 0
                else:
                    other_pair_factor = n // i

                factor_sum += (i + other_pair_factor + 1)

        if n < factor_sum :
            abundant_num_list.append(n)

def NonAbundantSums():

    abundant_sum_list = []
    all_num_list = []
    non_abun_list = []
    non_abun_sum = 0

    for i in range(len(abundant_num_list)):
        for j in range(i, len(abundant_num_list)):
            if abundant_num_list[i] + abundant_num_list[j] <= 28123:
                abundant_sum_list.append(abundant_num_list[i] + abundant_num_list[j])

    for i in range(1, 28124):
        all_num_list.append(i)

    non_abun_list = [int(a) for a in (set(all_num_list) - set(abundant_sum_list))]

    for i in range(len(non_abun_list)):
        non_abun_sum += non_abun_list[i]

    print(non_abun_sum)

checkAbundant()
NonAbundantSums()

end = time.time() - start
print("Done in", end, "seconds")

如果它看起来效率低下,我知道,我是编码新手。 Python是我的第一门编程语言。我注意到我的non_abun_list有一个怪异的问题,当检索set(all_num_list)和set(abundant_sum_list)的差时,rich_sum_list的第一和第二个索引是2和30,所以在我看来,non_abun_list应当像

  

[1、2、3、4 ...,22、23、25、26、27、28、29、31、32]

相反,我得到了这个

  

[1、2、3、4 ...,22、23、8209、25、26、27、28、29、8219、31、32]

,我不知道该如何获得此列表。 有人可以向我解释我的代码有什么问题吗? 我的结果是〜25秒内4352518 答案是4179871

2 个答案:

答案 0 :(得分:0)

这不是答案
(由于代表的要求,OP无法参与聊天)

您应该考虑自己的编码风格。如果您编写简洁的函数来执行任务,并让这些函数返回一个或多个值,那么您可以轻松地测试这些函数以查看它们是否有效。这样可以更轻松地确定什么在起作用。

例如,当检查丰度时,您必须做两件事:找到一个数字的除数,然后将它们的和与该数字进行比较。

def divisors(n):
    '''return divisors of n'''
    d = [1]
    for i in range(2, int(pow(n,.5))+1):
        if (n % i) == 0:
            other = n // i
            if other == i:
                pair = [i]
            else:
                pair = [i,other]
            d.extend(pair)
    return d

def check(n):
    '''return True if abundant'''
    return sum(divisors(n)) > n

现在,如果您开始遇到问题,则可以轻松针对已知输入和输出测试这两个功能。知道它们有效后,您就不必将其视为错误的来源。

用法:

abundant_numbers = []
for n in range(12,28124):
    if check(n):
        abundant_numbers.append(n)

测试几个数字:

>>> divisors(16)
[1, 2, 8, 4]
>>> divisors(1056)
[1, 2, 528, 3, 352, 4, 264, 6, 176, 8, 132, 11, 96, 12, 88, 16, 66, 22, 48, 24, 44, 32, 33]
>>> check(16)
False
>>> check(1056)
True
>>> 

是的,看起来不错:)。

答案 1 :(得分:0)

    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:         
            if math.floor(math.sqrt(n)) == math.sqrt(n) == i:
                other_pair_factor = 0
            else:
                other_pair_factor = n // i

            factor_sum += (i + other_pair_factor)

    factor_sum += 1

对于checkAbundant()的这一特定部分,我应该在第3行添加“ == i”,因为我只希望重复两次的因子只对平方数计数一次

例如,我要称呼为36的配对因子为1 x 36、2 x 18、3、12、4 x 9、6 x 6。

为了提高效率,我只找到因子对的前一半,另一半通过n // i获得。因此,为了拥有一定数量的适当因子的总和,我不能有重复的因子。

我没有添加“ == i”,所以对于任何平方丰富的数字,求和总因数时都不会考虑它们的另一半。

我在checkAbundant()中修复的另一个错误在第8行中,其中factor_sum + =(i + other_pair_factor +1)

这导致每个循环,factor_sum将有一个额外的1,这将破坏结果。为了解决这个问题,我在for循环后添加了1

总的来说,我会说这是一个新秀错误。 >。<< / p>