【问题标题】:Project Euler #23 - Python Non Abundant SumsProject Euler #23 - Python 非丰富的总和
【发布时间】:2017-08-11 15:31:03
【问题描述】:

我一直在处理Project Euler #23

这是任务:

问题 23

一个完全数是一个数,它的真因数之和正好等于这个数。例如,28 的因数之和为 1 + 2 + 4 + 7 + 14 = 28,这意味着 28 是一个完美数。

如果一个数 n 的真因数之和小于 n 则称为不足数,如果该数之和超过 n 则称为丰富数。

由于12是最小的丰富数,1 + 2 + 3 + 4 + 6 = 16,所以可以写成两个丰富数之和的最小数是24。通过数学分析,可以证明所有大于 28123 的整数可以写成两个丰富数之和。然而,这个上限不能通过分析进一步降低>即使已知不能表示为两个丰富数之和的最大数小于这个限制。

找出所有不能写成两个丰富数之和的正整数之和。

这是我的代码:

import math

def getDivisors(num):
    n = math.ceil(math.sqrt(num))
    total = 1
    divisor = 2
    while (divisor < n):
        if (num%divisor == 0):
            total += divisor
            total += num//divisor
        divisor+=1
    return total

def isAbundant(num):
    if (getDivisors(num) > num):
        return True
    else:
        return False

abundentNums = []
for x in range (0,28124):
    if (isAbundant(x)):
        abundentNums.append(x)
del abundentNums[0]

sums = [0]*28124
for x in range (0, len(abundentNums)):
    for y in range (x, len(abundentNums)):
            sumOf2AbundantNums = abundentNums[x]+abundentNums[y]
            if (sumOf2AbundantNums<= 28123):
                if (sums[sumOf2AbundantNums] == 0):
                    sums[sumOf2AbundantNums] = sumOf2AbundantNums

total = 0
for x in range (1,len(sums)):
    if (sums[x] == 0):
        total +=x

print('\n', total)

我得到的总价值是4190404。正确答案是4179871。我花了一个小时查看我的代码,但找不到错误。我应该改变什么来纠正错误?我的答案很接近。提前致谢

PS。我是 python 新手。运行时间为 25 秒,任何优化都会很有用。

【问题讨论】:

  • 这是为了参加 Hackerrank 比赛吗?
  • @AnthonyCollins Project Euler 是一个有数学/拼图问题的网站。
  • 不,体育是为了娱乐和打发时间
  • 您应该能够在此处包含一些动态编程方法(或缓存递归)。例如。如果 28 的除数已知,您可以将这些知识用于 56、84 等。这样可以节省很多。
  • 哦,好的。我的 b。当前有一个名为“ProjectEuler+”的人力资源竞赛,当我读到这篇文章时,我想到了它,但我不确定这是否相关。继续哈哈

标签: python algorithm math


【解决方案1】:

您的getDivisors 函数不正确。它不计算平方数的根除数(例如,如果num=25,它将返回 1)。这是一个更正的版本:

def getDivisors(num):
    if num==1:
        return 1
    n = math.ceil(math.sqrt(num))
    total = 1
    divisor = 2
    while (divisor < n):
        if (num%divisor == 0):
            total += divisor
            total += num//divisor
        divisor+=1
    if n**2==num:
        total+=n
    return total

通过这个函数,我得到了所需的结果4179871

【讨论】:

  • 不是divisor &lt;= math.floor(math.sqrt(num))divisor &lt; math.ceil(math.sqrt(num)) 一样
  • @Varun Narayanan 请注意,我编辑了我的答案(以对您的代码进行最小的更改)。
  • 但是关于“不是除数 之间就有区别
  • 谢谢,if (n**2 == num): total -= n 并设置 `n = math.ceil(math.sqrt(num))` 成功了。 :)
【解决方案2】:

这段代码在我的电脑上运行 6 秒:

from math import sqrt
import itertools
import functools
import operator
#simplicity test
def fuc(a):
    d = 1
    z = 0
    while d<= sqrt(a):
        d = d + 1
        if a == 2:
            z = a
        elif (a%d) == 0:
            z = False
            break

        else:
            z = a
    return z
#prime number divisors
def func(value):
    v = []
    d = 1
    value1= value# for optimization
    while d <= sqrt(value1):
        d+=1
        if fuc(d)!= False and value1 % d == 0:
            v.append(d)
            value1 = value1/d
            d = 1
    if value1 != value and value1 != 1:
        v.append(value1)
    return v
# all number divisors without 1 and source number
def calculate_devisors(n):
    prime_multiples_list = func(n)
    unique_combinations = set()
    for i in range(1, len(prime_multiples_list)):
        unique_combinations.update(set(itertools.combinations(prime_multiples_list,i)))
        combinations_product = list(functools.reduce(operator.mul,i) for i in unique_combinations)
        combinations_product.sort()
    try:
        return combinations_product
    except:
        return []

abundentNums = []

for n in range(1,28123):
    if sum(calculate_devisors(n))+1>n:
        abundentNums.append(n)

sums = [0]*28124
for x in range (0, len(abundentNums)):
    for y in range (x, len(abundentNums)):
        sumOf2AbundantNums = abundentNums[x]+abundentNums[y]
        if (sumOf2AbundantNums<= 28123):
            if (sums[sumOf2AbundantNums] == 0):
                sums[sumOf2AbundantNums] = sumOf2AbundantNums
ans = 0
for i in range(1,len(sums)):
    if sums[i]==0:
        ans+=i
print(ans)

【讨论】:

    【解决方案3】:

    我对上面提到的代码做了一些更改,我在 13 秒内得到了正确答案。我的CPU是英特尔酷睿i5。这是我的代码:

    from array import array
    import math
    
    
    def find_abundant(number):
        sum_factor = 1
        value = math.ceil(math.sqrt(number))
        if number == 1:
            return False
        for i in range(2, value):
            if number % i == 0:
                sum_factor += (i+(number//i))
        if value**2 == number:
            sum_factor += value
        if sum_factor > number:
            return True
        else:
            return False
    
    
    numbers = [0]*28123
    abundant_numbers = array("i", [])
    for abundant in range(1, 28124):
        if find_abundant(abundant):
            abundant_numbers.append(abundant)
    
    for x in abundant_numbers:
        for y in abundant_numbers[0:abundant_numbers.index(x)+1]:
            z = x+y
            if z < 28124 and numbers[z-1] == 0:
                numbers[z-1] = z
    
    
    _sum = 0
    for vary in range(1, len(numbers)+1):
        if numbers[vary-1] == 0:
            _sum += vary
    print(_sum)}
    

    【讨论】:

      【解决方案4】:

      我发现这些小调整可能有助于减少总时间。我在大约 4 秒内就在我的电脑上收到了。

      from math import sqrt
      from itertools import compress
      start = time.process_time()
      
      abundant_nos = []
      for i in range(12,28123):
          factor = 0
          for j in range(2,int(sqrt(i))+1):
              if i%j == 0:
                  factor+= j + i//j
                  if j == sqrt(i):
                      factor -= j
          if factor>i:
              abundant_nos.append(i)
      num_list = [True]*28123
      k = 0
      for i in abundant_nos:
          for j in abundant_nos[k:]:
              if(i+j>28123): break
              num_list[i+j-1] = False
          k+=1
      answer = sum(compress(range(1,28124),num_list))
      
      print(answer)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-24
        • 1970-01-01
        • 2014-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-14
        相关资源
        最近更新 更多