【问题标题】:Efficiently finding the number of divisors in Haskell在 Haskell 中有效地找到除数的数量
【发布时间】:2015-11-17 05:25:36
【问题描述】:

尝试在 Haskell 中解决 Project Euler 的第 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
 We can see that 28 is the first triangle number to have over five divisors.

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

我的解决方案适用于少量除数(例如,给定 5,它返回 28),但是当输入 500 时,它似乎无限期挂起。

-- Lazily generates infinite list of triangle numbers.
triangleNumbers :: [Integer]
triangleNumbers = map (\x -> sum [1..x]) [1..]

-- Given a number, returns the a tuple of how many divisors it has and the number.
numDivisors :: Integer -> (Int, Integer)
numDivisors num = (length [x | x <- [1..num], num `mod` x == 0], num)

p12 :: Integer
p12 = snd $ head $ filter (\x -> fst x > 500) $ map numDivisors triangleNumbers

你知道我做错了什么吗?谢谢!

【问题讨论】:

  • 另一个提示:注意第n个三角数是n*(n+1)/2,因为nn+1是互质数...
  • [思考] 那么,给定n,得到它的质因数和n+1,然后将它们的每一个组合相乘得到三角数的所有因数??

标签: haskell count factors number-theory factorization


【解决方案1】:

问题是查找除数的函数非常慢,因为它会测试所有数字。还有更有效的功能。例如,请参阅 StackOverflow 上此问题的答案:Two simple codes to generate divisors of a number. Why is the recursive one faster?

但如果你用谷歌搜索一下,你会发现很多其他算法。

【讨论】:

    【解决方案2】:

    另一个问题是您生成的三角数虽然正确,但效率非常低。例如,要计算第 11 个数字,您要对 [1..11] 求和,然后要计算第 12 个数字,您要对 [1..12] 求和,它不使用先前计算的结果。

    正如我在评论中提到的,您可以使用n*(n+1)/2 直接计算第 n 个三角形数。然而,即使你不知道这个公式,你也可以通过使用这样的递归来利用连续三角形数之间的相似性:

    triangulars = go 1 2
      where go s n = s : go (s+n) (n+1)
    

    这种递归也被scanl函数捕获:

    triangulars = scanl (+) 1 [2..]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      • 1970-01-01
      • 2014-05-13
      • 1970-01-01
      • 2021-08-08
      相关资源
      最近更新 更多