【问题标题】:Project Euler #12欧拉计划 #12
【发布时间】:2017-03-11 17:05:15
【问题描述】:

12 三角形数的序列是由自然数相加生成的。所以第 7 个三角形数是 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28。前十项是:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

让我们列出前七个三角形数的因数:

  • 1:1
  • 3: 1,3
  • 6: 1,2,3,6
  • 10: 1,2,5,10
  • 15: 1,3,5,15
  • 21: 1,3,7,21
  • 28: 1,2,4,7,14,28

我们可以看到,28 是第一个有五个以上除数的三角形数。

第一个有五百多个除数的三角形数的值是多少?

定义一个列出数字因数的方法 遍历序列直到找到一个包含 500 个因子的三角形 返回具有 500 个因数的数字 if factor.count == 500

def factors(num)
  current_number = 1 
  factors_list= []
  while current_number <= num
    if is_factor(num,current_number)
      factors_list << current_number
    end
    current_number += 1 
  end
  return factors_list
end

def is_factor(big,small)
  if big % small == 0 
    return true 
  else 
    false 
  end
end     

def big_triangle(num) #500
  triangles = [1]
  natural_numbers = 1
  while factors(natural_numbers).count != num 
    triangles << natural_numbers
    natural_numbers += 1     
  end
  triangles.select { |n| factors(n).count == num }
end

【问题讨论】:

  • 我已经检查了问题的定义,没有必要存储所有的三角形数字。只需要返回除数超过 500 的第一个三角形数。您是否正在努力做到这一点??
  • 你的最后两句话是矛盾的。第一个声明您想要第一个具有超过 500 个因子的三角形数,这就是问题的通常表述方式。第二个表示您想要第一个具有正好 500 个因子的三角形数(尽管您可能意味着超过 500 个)。我不知道是否有正好有 500 个因数的三角形数,如果有,需要多长时间才能找到。

标签: ruby


【解决方案1】:

我们当然应该使用 Ruby 提供的相关方法。在这种情况下,一种这样的(类)方法是Prime::prime_division。例如,

require 'prime'

Prime.prime_division(2106)
  #=> [[2, 1], [3, 4], [13, 1]]

这告诉我们 2106 有素数 2313,并且

2**1 * 3**4 * 13**1
  #=> 2106

2106 有多少个因数?每个因素的形式

2**a * 3**b * 13**c

0 &lt;= a &lt;= 10 &lt;= b &lt;= 40 &lt;= c &lt;= 1。这包括a = b = c = 0,因子为1a, b, c = 1, 4, 1,因子为2106。因此因子数等于

(1+1) * (4+1) * (1+1)
  #=> 20

也就是说,对于每次包含 2 的次数(01),3 可以包含在 04 之间,并且对于这 10 对中的每一对, 13 可以包含 01 次。

举一个更简单的例子,考虑三角形数45

Prime.prime_division(45)
  #=> [[3, 2], [5, 1]]

因此因子数为

(2+1) * (1 + 1)
  #=> 6

这些因素是

3**0 * 5**0 #=>  1
3**0 * 5**1 #=>  5 
3**1 * 5**0 #=>  3 
3**1 * 5**1 #=> 15 
3**2 * 5**0 #=>  9 
3**2 * 5**1 #=> 45 

因此我们可以写

def nbr_factors(n)
  Prime.prime_division(n).reduce(1){ |t,(_,m)| t * (m+1) }
end

nbr_factors(2106)
  #=> 20
nbr_factors(45)
  #=> 6

现在可以很容易地获得所需的结果。

def first_triangle_nbr_with_min_nbr_divisors(min_nbr_divisors)
  tri = 0
  1.step.each do |i|
    tri += i
    break tri if nbr_factors(tri) >= min_nbr_divisors
  end
end

first_triangle_nbr_with_min_nbr_divisors   6 #=>         28
first_triangle_nbr_with_min_nbr_divisors  20 #=>        528
first_triangle_nbr_with_min_nbr_divisors 501 #=> 76_576_500

最后一个例子的最后几个计算如下。

...
i=12372, tri=76539378, nbr_factors(tri)=16
i=12373, tri=76551751, nbr_factors(tri)=8
i=12374, tri=76564125, nbr_factors(tri)=96
i=12375, tri=76576500, nbr_factors(tri)=576

【讨论】:

  • 很好地使用 Prime 类
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多