Haskell函数处理时间较长

Haskell函数处理时间较长,haskell,optimization,Haskell,Optimization,我在做欧拉计划的第12题,我必须找到第一个有501个除数的三角形数。所以我和Haskell做了这个 divS n = [ x | x <- [1..(n)], n `rem` x == 0 ] tri n = (n* (n+1)) `div` 2 divL n = length (divS (tri n)) answer = [ x | x <- [100..] , 501 == (divL x)] divsn=[x | x一些优化技巧: 检查1和sqrt(n)之间的除数。我保

我在做欧拉计划的第12题,我必须找到第一个有501个除数的三角形数。所以我和Haskell做了这个

divS n = [ x | x <- [1..(n)], n `rem` x == 0 ]
tri n = (n* (n+1)) `div` 2
divL n = length (divS (tri n))
answer = [ x | x <- [100..] ,  501 == (divL x)]

divsn=[x | x一些优化技巧:

  • 检查1和sqrt(n)之间的除数。我保证你不会发现任何超过该限制的除数(除了数字本身)
  • 不要建立一个除数列表并计算该列表,而是直接计算它们

您需要使用除数函数的属性:


注意,n和n+1总是互质的,因此可以得到d(n*(n+1)/2)将先前计算的值相乘。

对数字进行素数分解,然后使用因子分解查找除数,可能比对所有数字进行尝试除法要快。如果使用C而不是Haskell,则函数仍将花费大量时间

为了更快,您需要改进算法,使用上述答案中的建议。我建议相应地更改标题和问题描述。接下来,我将删除此评论

如果你愿意,我可以通过分享我的解决方案来破坏这个问题

现在,我将为您提供我的顶级代码:

main =
  print .
  head . filter ((> 500) . length . divisors) .
  map (figureNum 3) $ [1..]

算法的改进在于
除数
函数。你可以使用拉维斯基的建议进一步改进它,但这需要不到100毫秒的时间。

它应该……但你似乎正在建立一个大于500个除数的三角形数的列表,而不仅仅是寻找第一个除数。我不喜欢哈斯克尔,所以我可能会被扭曲g这里:)对于每个除数d,1@Dave Hinton:正确,但是这些除数可以用一个除法找到。一般来说,在这类任务中,查看得到的数字的素数因子是一个很好的启发式方法-501=3*167,但是如果你想在进行过程中建立素数列表,你需要检查所有的正数,而不是ju塞德:你说得对极了。我不知道哪一个是渐进的快,但我的直觉告诉我,我的解决方案会比Jonno_FTW原来的解决方案快。我是基于必须找到的除数的数量,以及加法比除法快得多的事实优化筛选也可以提供显著的恒定因子加速。我曾经通过重用相同的一小块RAM实现了12倍的加速。但是缓存优化Haskell可能很难。尽管如此,rawicki的解决方案看起来要好得多。实际上,如果你将Eratosthenes筛选与rawickis的想法结合起来,它非常有用。我只是在python中,找到解决方案只需要一小部分的时间。查看这两个想法也将有助于解决Euler项目的其他问题。