繁体   English   中英

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

[英]Project Euler #23 - Non Abundant Sums

这是任务:

问题23

理想数字是其适当除数之和与该数字完全相等的数字。 例如,适当除数为28的总和将为1 + 2 + 4 + 7 + 14 = 28,这意味着28是一个理想数。

如果数字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

这不是答案
(由于代表的要求,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
>>> 

是的,看起来不错:)。

    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

总的来说,我会说这是一个相当新手的错误。 > <

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM