我遇到了一个问题,我首先找到一个数字的阶乘,然后返回在阶乘中获得的数字位数。 我写了这个程序,它工作得很好。但时间是5.0015秒,我必须在1秒内完成。如何减少这个?
以下是我的计划:
def factorial(n):
fact = 1
for y in xrange(1,n+1):
fact = fact * y
return fact
t = int(raw_input())
raw_input()
for x in xrange(t):
n = int(raw_input())
print len(str(factorial(n)))
答案 0 :(得分:3)
使用数学的力量,避免完全计算阶乘。
数字的基数10对数是10需要被提升到等于该数字的幂。例如,math.log10(10) == 1
,math.log10(11) == 1.0413926851582251
,math.log10(100) == 2
等
这意味着最小整数比数字的log10大得多(即ceil(log10(n)) + (1 if log10(n).is_integer() else 0)
)是该数字中的位数。
此外,log10(a * b) = log10(a) + log10(b)
。
这意味着log10(factorial(n)) == sum(log10(a) for a in range(1, n+1))
最后,该阶乘的长度为:
math.ceil(sum(math.log10(a) for a in xrange(1, n+1)))
答案 1 :(得分:1)
我建议使用Stirling's approximation for log(n!):
from math import ceil, log, pi
def log_fact(n):
# using Stirling's approximation to calculate log10(n!)
n = float(n)
return (
n * log(n)
- n
+ log(2 * pi * n) / 2.
+ 1/( 12 * n )
- 1/( 360 * n**3)
+ 1/(1260 * n**5)
) / log(10)
猜测n
的值大约为60000;测试我得到了
import math
n = 60000
%%timeit
# @SheeshMosin
len(str(factorial(n))) # 3.93 s
%%timeit
# @MaxNoel
math.ceil(sum(math.log10(a) for a in range(1, n+1))) # 16.1 ms
# (250 times faster)
%%timeit
# @HughBothwell
math.ceil(log_fact(n)) # 3.62 µs
# (1.08 million times faster)
答案 2 :(得分:-4)
您可以尝试递归函数。