Python和带有分数的因子

时间:2014-06-12 13:06:37

标签: python python-3.x

我知道这段代码很难看,但我想知道是否有人能告诉我在python中确定这样的阶乘方法:

import math

print(math.factorial(6400001) / (math.factorial(1) * math.factorial(103040)
    * math.factorial(181760) * math.factorial(48000) * math.factorial(119040)
    * math.factorial(78080) * math.factorial(64000) * math.factorial(163840)
    * math.factorial(140160) * math.factorial(185600) * math.factorial(255360)
    * math.factorial(131840) * math.factorial(109440) * math.factorial(104960)
    * math.factorial(144000) * math.factorial(104320) * math.factorial(69120)
    * math.factorial(96000) * math.factorial(67200) * math.factorial(49280)
    * math.factorial(138240) * math.factorial(103040) * math.factorial(154240)
    * math.factorial(206080) * math.factorial(49920) * math.factorial(126720)
    * math.factorial(254720) * math.factorial(83200) * math.factorial(48000)
    * math.factorial(80640) * math.factorial(142080) * math.factorial(124800)
    * math.factorial(106880) * math.factorial(170880) * math.factorial(128640)
    * math.factorial(44160) * math.factorial(110720) * math.factorial(76800)
    * math.factorial(218240) * math.factorial(73600) * math.factorial(72960)
    * math.factorial(40320) * math.factorial(68480) * math.factorial(74240)
    * math.factorial(29440) * math.factorial(123520) * math.factorial(76160)
    * math.factorial(76800) * math.factorial(76160) * math.factorial(28160)
    * math.factorial(94080) * math.factorial(96640) * math.factorial(124160)
    * math.factorial(39040) * math.factorial(83200) * math.factorial(46080)
    * math.factorial(93440) * math.factorial(181760) * math.factorial(70400)
    * math.factorial(81280) * math.factorial(99200) * math.factorial(77440)
    * math.factorial(4480) * math.factorial(3840) * math.factorial(9600)))

2 个答案:

答案 0 :(得分:1)

我不知道你在做什么,但也许

import math
import operator

numbers = (1, 103040, 181760, 48000, 119040, 78080, 64000, 163840, 140160, 185600,
    255360, 131840, 109440, 104960, 144000, 104320, 69120, 96000, 67200, 49280,
    138240, 103040, 154240, 206080, 49920, 126720, 254720, 83200, 48000, 80640, 142080,
    124800, 106880, 170880, 128640, 44160, 110720, 76800, 218240, 73600, 72960, 40320,
    68480, 74240, 29440, 123520, 76160, 76800, 76160, 28160, 94080, 96640, 124160, 39040,
    83200, 46080, 93440, 181760, 70400, 81280, 99200, 77440, 4480, 3840, 9600)
print(math.factorial(6400001) / reduce(operator.mul, (math.factorial(i) for i in numbers)))

可能是你之后的......

答案 1 :(得分:0)

第一次改进,虽然仍然太慢:

from collections import Counter
from heapq import heapify, heappop, heappush, heappushpop

def fast_mul_many(numbers):
    heapify(numbers)

    x = heappop(numbers)
    while numbers:
        y = heappop(numbers)
        x = heappushpop(numbers, x * y)

    return x

start = 6400001

to_divide = [
    1,      103040, 181760, 48000,  119040, 
    78080,  64000,  163840, 140160, 185600, 
    255360, 131840, 109440, 104960, 144000, 
    104320, 69120,  96000,  67200,  49280,  
    138240, 103040, 154240, 206080, 49920,  
    126720, 254720, 83200,  48000,  80640,  
    142080, 124800, 106880, 170880, 128640, 
    44160,  110720, 76800,  218240, 73600,  
    72960,  40320,  68480,  74240,  29440,  
    123520, 76160,  76800,  76160,  28160,  
    94080,  96640,  124160, 39040,  83200,  
    46080,  93440,  181760, 70400,  81280,  
    99200,  77440,  4480,   3840,   9600,   
]

factors = Counter(range(1, start+1))

for remove in to_divide:
    factors.subtract(range(1, remove+1))

positives = Counter() + factors
negatives = Counter() - factors

fraction_top = fast_mul_many(list(positives.elements()))
fraction_bottom = fast_mul_many(list(negatives.elements()))

return fraction_top / fraction_bottom

这是一项改进。这至少是您发布的原始文件的50倍。我猜它已经超过50次了,但它需要一段时间来计算原始时间...

from collections import Counter
from heapq import heapify, heappop, heappush, heappushpop

def fast_mul_many(numbers):
    heapify(numbers)

    x = heappop(numbers)
    while numbers:
        y = heappop(numbers)
        x = heappushpop(numbers, x * y)

    return x

start = 6400001

to_divide = [
    1,      103040, 181760, 48000,  119040, 
    78080,  64000,  163840, 140160, 185600, 
    255360, 131840, 109440, 104960, 144000, 
    104320, 69120,  96000,  67200,  49280,  
    138240, 103040, 154240, 206080, 49920,  
    126720, 254720, 83200,  48000,  80640,  
    142080, 124800, 106880, 170880, 128640, 
    44160,  110720, 76800,  218240, 73600,  
    72960,  40320,  68480,  74240,  29440,  
    123520, 76160,  76800,  76160,  28160,  
    94080,  96640,  124160, 39040,  83200,  
    46080,  93440,  181760, 70400,  81280,  
    99200,  77440,  4480,   3840,   9600,   
]

factors = Counter(range(2, start+1))

for remove in to_divide:
    factors.subtract(range(2, remove+1))

max_key = max(factors)
for key in sorted(factors.keys()):
    if key > 10000: break

    if factors[key] == 0:
        continue

    for i in range(max_key//key, 1, -1):
        n = factors.pop(i * key, 0)
        factors[i] += n
        factors[key] += n

positives = Counter() + factors
negatives = Counter() - factors

fraction_top    = fast_mul_many([x**count for x, count in positives.items()])
fraction_bottom = fast_mul_many([x**count for x, count in negatives.items()])

fraction_top // fraction_bottom