您的问题有一个简单而有效的解决方案。需要注意的是n!
是:
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * ... * n
让我们想想一个主要因素有多少次出现在本产品,例如2
。 每隔2
出现一次。但每4
因素一次出现两次。并且每8
因子一次出现三次等。 换句话说,因子2
将出现在n!
sum(n//(2**e) for e in range(1, n))
次。对于任何主要因素k
也是如此。
您可以实现此计算有:现在
import itertools as it
def exp_for_factor_in_factorial(factor, n):
total = 0
for e in it.count(1):
if factor ** e > n:
break
total += n // factor**e
return total
,为了找到我们需要找到所有素数达n
的n!
所有的主要因素,这是很容易使用埃拉托色尼完成:
import math
def sieve(n):
nums = [True] * (n+1)
nums[:2] = [False]*2
nums[4::2] = [False] * math.ceil((n-3)/2)
for i in range(3, int((n+1)**.5)+1, 2):
if nums[i]:
for j in range(i*i, n+1, 2*i):
nums[j] = False
return [i for i,k in enumerate(nums) if k]
这使我们能够获得的n!
的分解:
def get_factorization_factorial(n):
primes = sieve(n)
factors = []
for p in primes:
factors.append((p, exp_for_factor_in_factorial(p, n)))
return factors
最后,计算除数的数量从因式分解你可以使用你已经提到的公式:
import operator as op
from functools import reduce
def get_num_divisors(factorization):
return reduce(op.mul, (e+1 for _, e in factorization), 1)
所以最终的答案可以作为获得:
def divs_of_squared_fact(n):
return get_num_divisors((p, 2*e) for p, e in get_factorization_factorial(n))
请注意,此解决方案极其比你更好的性能:
In [41]: %%timeit
...: for i in range(2, 1000):
...: x = divs_of_squared_fact(i)
...:
1 loops, best of 3: 276 ms per loop
In [42]: %%timeit
...: for i in range(2, 1000):
...: x = divisorsOfFactorialSquare(i)
...:
1 loops, best of 3: 7.89 s per loop
它能够产生除数的数0在约2ms
,而另外一个需要近半秒:
In [47]: %timeit divs_of_squared_fact(5000)
100 loops, best of 3: 2.07 ms per loop
In [48]: %timeit divisorsOfFactorialSquare(5000)
1 loops, best of 3: 439 ms per loop
好吧,其实答案有不同的渐近复杂性,以便增加参数当差趋于无穷。
对于这样的问题Vektor88我想了想,也对代码审查你可能会发现在http://cs.stackexchange.com/ – Vektor88 2014-11-02 08:52:34
@更好的答案,但我认为这是一个更好的地方。 – 2014-11-02 08:54:01
我不是downvoter,但我真的认为,当它的性能,或复杂的事情,CS是一个更好的地方。但这只是一个建议。你肯定知道并使用这个网站更然后我:) – Vektor88 2014-11-02 09:16:41