2个小时以来,我一直在尝试查找问题,正确的答案是4179871,但我一直只收到4177763,
一个完美数是一个其适当除数之和的数字 完全等于数字。例如,适当的总和 28的除数是1 + 2 + 4 + 7 + 14 = 28,这意味着28 是一个完美的数字。
如果数字n的适当除数之和为 小于n,并且如果总和超过n,则称为丰富。
因为12是最小的丰富数,所以1 + 2 + 3 + 4 + 6 = 16,因此 可以写为两个丰富数字之和的最小数字 是24。通过数学分析,可以证明所有整数 大于28123可以写为两个丰富数字的总和。 但是,无法通过分析进一步降低此上限 即使已知最大的数字 表示为两个丰富数字之和小于此限制。
查找所有不能写为的正整数之和 两个丰富数字的总和。
def factors(num) # function that returns array of factors
factorsNums = []
for i in 1..Math.sqrt(num).ceil
if num % i == 0
factorsNums.push(i) if i != num
factorsNums.push(num / i) if ((num / i) < num) && ((factorsNums.include? (num / i)) == false)
end
end
factorsNums
end
abundantNumbers = []
for i in 1..28123 #This loop will push into the array "abundantNumbers" each number from 1 to 28123 that is an abundant number (a number in which the sum of its divisors is bigger than the number itself)
abundantNumbers.push(i) if factors(i).inject(0, :+) > i
end
abundantSums = []
#this 2 dimensional loop will find the every possible sum of 2 abundant numbers from which we got in the last for loop and push them into another array "abundantSums"
for i in 0...abundantNumbers.length
for j in i...abundantNumbers.length
sum = abundantNumbers[i] + abundantNumbers[j]
abundantSums.push(sum) if sum <= 28123
end
end
abundantSums = abundantSums.uniq.sort #remove duplicates and sort the array
notSums = []
for i in 1..28123 #find numbers which are not the sum of 2 abundant numbers and push them into the array "notSums"
notSums.push(i) if (abundantSums.include? i) == false
end
print notSums.inject(0, :+) #print out sum of array elements that are not sums of abundant numbers
答案 0 :(得分:2)
问题是如何处理因子,数组中包含因子的重复项,这是解决方法:
def factors(num) # function that returns array of factors
factorsNums = []
for i in 1..Math.sqrt(num).ceil
if num % i == 0
factorsNums.push(i) if i != num && !factorsNums.include? i
factorsNums.push(num / i) if ((num / i) < num) && ((factorsNums.include? (num / i)) == false)
end
end
factorsNums
end
答案 1 :(得分:1)
在构造一个返回给定正整数的适当因子数组的方法时,我们可以使用方法Prime::prime_division,该方法确定每个正整数的素数分解。例如,
require 'prime'
Prime.prime_division(180)
#=> [[2, 2], [3, 2], [5, 1]]
这意味着
180 = 2**2 * 3**2 * 5**1
此外,180
的每个因子都等于
2**n2 * 3**n3 * 5**n5
其中0 << n2 << 2
,0 << n3 << 2
和0 <= n5 <= 1
。 适当因素是除180
之外的所有其他因素
(2+1)*(2+1)*(1+1) - 1 #=> 17
因此,我们可以如下定义OP的方法factors
(我将其重命名为proper_factors
)。
def proper_factors(n)
first, *rest = Prime.prime_division(n).
map { |m,pow| (0..pow).map { |p| m**p } }
first.product(*rest).
map { |arr| arr.reduce(:*) } - [n]
end
proper_factors(180)
#=> [1, 5, 3, 15, 9, 45, 2, 10, 6, 30, 18, 90, 4, 20, 12, 60, 36]
接下来,创建一个介于12和28123之间的大量数字的数组。
max_val = 28123
abundants = (12..max_val).select { |n| proper_factors(n).sum > n }
#=> [12, 18, 20, 24, 30, 36, 40, 42, 48, 54, 56, 60, 66, 70, 72, 78, 80,
# ...
# 12078, 12080, 12084, 12090, 12096, 12100, 12102, 12104, 12108, 12110,
# ...
# 28086, 28092, 28098, 28100, 28104, 28110, 28112, 28116, 28120, 28122]
abundants.size
#=> 6965
不等于两个整数的和的正数之和等于1和28123之间的数字之和(算术级数之和)减去1和28123之间等于两个之和的数字之和大量的。等于两个丰富数字之和的数字比不具有该属性的数字更容易计算,因此我们将所需的和计算为两个和之和。
1到28123之间的数字总和等于
all_sum = 28123*(1+28123)/2
#=> 395465626
我们现在计算1到28123之间的数字总和,该数字总和等于两个丰富数字的总和。为此,我们仅累加(按数组)不超过28123
的所有成对数字的总和。当然,这将产生许多重复项,因此我们必须uniq
对数组求和,然后再对其求和。 (我们可以累积成一个集合。)
half_max = max_val/2
#=> 14061
last_abundants_idx = abundants.size - 1
#=> 6964
sum_nbrs_sum_two = abundants.each_with_index.with_object([]) do |(n,i),found|
break found if n > half_max
(i..last_abundants_idx).each do |j|
m = n + abundants[j]
break if m > max_val
found << m
end
end.uniq.sum
#=> 391285755
这里数组found
和found.uniq
分别包含12148815
和26667
元素。 1
最后一步是以下步骤。
all_sum - sum_nbrs_sum_two
#=> 4179871
1请注意,第三行包含范围(i..last_abundants_idx)
,而不是(i+1..last_abundants_idx)
,以包括数字2*abundants[i]
。对于所有i
都是如此,但是对于大多数i
,2*abundants[i]
等于两个不同的丰富数之和。实际上,如果将i..
更改为i+1..
,总和(391285755
)仅减少64
。