如何为一个数字生成所有可能的除数产品?

时间:2014-07-13 14:29:00

标签: python algorithm python-3.x primes prime-factoring

我正在努力实施一种算法,它可以为数字提供可能的产品。例如,对于N=24,这些是:

24*1, 12*2, 8*3, 6*4, 4*3*2, 3*2*2*2

我已经实现了一个函数,该函数计算给定数字的素数因子的幂(例如2^33^1 N=24。但我无法弄清楚如何从主要因素中得到除数组合。

编辑:这是我尝试过的:

def divisors(factors): # prime factors, e.g. [2,2,2,3] for 24
    yield list(factors)

    d = factors.pop()

    for i in range(len(factors)):
        m = [d*factors[i]] + factors[:i] + factors[i+1:]
        yield from divisors(m)

2 个答案:

答案 0 :(得分:5)

你不会说出你需要这个号码的大小,或者速度是否是一个问题,但这里是一个非常简单的未经优化的解决方案,应该适用于小输入({{1}小于n,比如说。

10**7

要解释代码,请考虑如何有条不紊地手动执行此操作。您可以从包含def products(n, min_divisor=2): """Generate expressions of n as a product of ints >= min_divisor.""" if n == 1: yield [] for divisor in range(min_divisor, n+1): if n % divisor == 0: for product in products(n // divisor, divisor): yield product + [divisor] 的产品开始。如果2是奇数,那就没有了。如果n是偶数,那么我们可以进行简单的递归:查找n的所有可能分解,然后为每个分解输出n // 2。一旦我们耗尽了包含decomposition * 2的所有产品,我们就会转向涉及2的产品。但是这里还有一个额外的复杂因素:在第一步中,我们已经发现所有涉及3的产品,所以为了避免重复的解决方案,我们希望限制在中的产品每个除数至少为2。因此,我们的递归调用需要跟踪上面的最小允许除数3。最后,我们需要一个基本案例:min_divisor可以表示为空产品。

以下是1的输出,包括您错过的n=24案例:

6*2*2

但这并不令人满意:正如其他评论者指出的那样,应该可以从素数因子分解计算>>> for product in products(24): ... print('*'.join(map(str, product))) ... 3*2*2*2 6*2*2 4*3*2 12*2 8*3 6*4 24 的乘法分区,甚至可以从素数因子分解中的指数列表中计算,只有在重建因素时才使用素数。这是上述的变体,与现有的素因数分解一起使用。还有很多提高效率的余地:特别是,n调用和后续过滤以忽略词典小于itertools.product的所有内容应该替换为启动的自定义迭代器< / em>来自min_exponents。但这应该是一个起点。

min_exponents

再次import itertools def exponent_partitions(exponents, min_exponents): """Generate all vector partitions of 'exponents', each of whose entries is lexicographically at least 'min_exponents'.""" if all(exponent == 0 for exponent in exponents): yield [] else: for vector in itertools.product(*(range(v+1) for v in exponents)): if vector >= min_exponents: remainder = tuple(x - y for x, y in zip(exponents, vector)) for partition in exponent_partitions(remainder, vector): yield partition + [vector] def divisor_from_exponents(primes, exponent_vector): """Reconstruct divisor from the list of exponents.""" divisor = 1 for p, e in zip(primes, exponent_vector): divisor *= p**e return divisor def multiplicative_partitions(primes, exponents): """Generate all multiplication partitions of product(p**e for p, e in zip(primes, exponents))""" if len(exponents) == 0: # Corner case for partitions of 1. yield [] else: initial_vector = (0,) * (len(exponents) - 1) + (1,) for partition in exponent_partitions(exponents, initial_vector): yield [divisor_from_exponents(primes, vector) for vector in partition] 的输出:我们将24写为24,因此素数的元组是2**3 * 3**1和相应的指数元组是(2, 3)

(3, 1)

关于生成和计算整数的乘法分区的大量文献。例如,请参阅OEIS A001055的链接和计算向量分区的SAGE functions

答案 1 :(得分:-1)

以下是您问题的最简单解决方案:

def prime_factors(n):
    i = 2
    factors = []
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
            factors.append(i)
    if n > 1:
        factors.append(n)
    return factors