【问题标题】:Algorithm slowness for Project Euler #20Project Euler #20 的算法缓慢
【发布时间】:2012-07-20 02:32:45
【问题描述】:

这是我要解决的问题:http://projecteuler.net/problem=20(求 100 中数字的总和!)

我正在使用 Lua,它只有 double 作为数字类型,所以我不得不手动处理。我使用的代码几乎与我在问题 16 中使用的代码相同(找到 2^1000 中的数字总和)。然而,这一次问题似乎超出了我的算法在相当长的时间内解决的问题——它达到了大约 32 个!在我必须等待超过 10 秒才能计算下一个总数之前,然后是 34!它比我等待的时间更长。有什么办法可以加快速度(使用“原始”Lua - 而不是 LuaJIT 或类似的东西)?

local sum = {1}
for i=1,100 do
    local carry = 0
    for v=1,#sum do
        local c = carry
        carry = 0
        local t = sum[v] * i
        while t >= 10 do
            t = t - 10
            carry = carry + 1
        end
        local s = t + c
        while s >= 10 do
            s = s - 10
            carry = carry + 1
        end
        sum[v] = s
    end
    if carry > 0 then
        sum[#sum+1] = carry
    end
    print(""..i.."! = "..getCharactersReversed(sum))
end

【问题讨论】:

标签: performance lua


【解决方案1】:

您的问题是(n+1)! 的十进制表示的长度可能比n! 的长度长一个以上。这首先发生在n == 14

14! =   87178291200
15! = 1307674368000

因此,您的最终carry 是 13,并且前导“数字”大于 10。从那时起,这个问题变得越来越严重,打印出 #sum 并且最终产生收益

15      11      13
16      12      20
17      13      35
18      14      64
19      15      121
20      16      243
21      17      510
22      18      1124
23      19      2585
24      20      6204
25      21      15511
26      22      40329
27      23      108888
28      24      304888
29      25      884176
30      26      2652528
31      27      8222838
32      28      26313083

并通过逐步减法将leading_number * i 减少到小于 10 的数字需要越来越长的时间。在某个点(估计约为 45),该值变得如此之大以至于t - 10 == t 并且您陷入了无限循环。 LuaJIT 根本帮不上忙。

所以你必须确保你永远不会写一个大于 9 的数字,例如通过减少循环中的最后一个进位,就像前面的数字一样,并根据需要添加尽可能多的数字。这样做,程序运行没有明显的延迟。

if carry > 0 then
    local w = #sum+1
    local cc = 0
    while carry > 0 do
        while carry >= 10 do
            carry = carry - 10
            cc = cc + 1
        end
        sum[w] = carry
        w = w+1
        carry = cc
        cc = 0
    end
end

但是通过除法确定数字和进位更简洁,并且对于较大的因素也更有效(当将数字乘以 100 时,结果平均为 450,需要 45 次减法,但两次除法就足够了所有因素)。

【讨论】:

    【解决方案2】:

    试试这个短代码:

        def factorial(n):
            return reduce(lambda x,y: x*y,[_ for _ in range(1,n+1)])
    
        print sum(map(int,list(str(factorial(100)))))
    

    【讨论】:

      猜你喜欢
      • 2015-12-25
      • 2015-07-28
      • 1970-01-01
      • 2021-07-21
      • 2021-12-23
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多