以下是我要解决的问题: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
答案 0 :(得分:5)
您的问题是(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次减法,但是两次除法就足够了因为所有因素)。
答案 1 :(得分:0)
试试这段简短的代码:
def factorial(n):
return reduce(lambda x,y: x*y,[_ for _ in range(1,n+1)])
print sum(map(int,list(str(factorial(100)))))