该代码块的优化版本是什么

时间:2019-03-29 18:18:32

标签: python

cnt = 0
N = int(raw_input())
for i in range(1,N+1):
    for j in range(1,N+1):
        for k in range(1,N+1):
            if (i*j)%k == 0:
                cnt+=1

给出python代码,是否可以进一步优化它,使cnt值正确。我尝试过的一种方法是在kth循环中计算因子,这会使复杂度从o(n ^ 3)变为o(n ^ 2root(n))

1 个答案:

答案 0 :(得分:2)

您可以采取几种措施来改善这一状况。 该算法计算i, j可整除的(k)个产品的数量,所有数字均在[1, N]范围内。您可以通过明智地选择循环限制来减少开销:

for i in range(1, N+1):
    for j in range(i, N+1):
        for k in range(i*j, N+1):
            if (i*j) % k == 0:
                cnt += 1

k除以i*jij必须包含必需数量的k的每个素数。您可以直接计算这些,而不必遍历所有可能性。从外部循环中的k开始,确定其主要因素,然后生成所有将覆盖这些因素的i*j组合。

从循环开始,为整个范围[2,N]生成素数分解。可以使用Eratosthenes的筛子来处理它,但是不要立即取消合成数的资格,而要保留其因素列表。例如,如果N = 10,您将使用方便的分解列表来完成此循环:

 2   2
 3   3
 4   2 2
 5   5
 6   2 3
 7   7
 8   2 2 2
 9   3 3
10   2 5

现在,您可以对每个i j k值进行分解。

for k in range(2, N):
    fact = # prime factors of k
    for i in range(2, N):
        if i has no factors in common with k:
            count += N // i  # We need j%k == 0; this is a simple division.
        else:
            divisors = # remove common i-factors from k-factors (reduce)
            new_i = # product of remaining factors
            count += N // new_i   # j must be a multiple of "reduced" k

例如,对于k=6,我们这样迭代:

i = 1: relatively prime to k; add (10 // 6) j-values: j=6 is the only solution
i = 2: Common factor of 2; treat as k = 6/2; add (10 // 3) j-values
i = 3: Common factor of 3; treat as k = 6/3; add (10 // 2) j-values
i = 4: Common factor of 2; treat as k = 6/2; add (10 // 3) j-values
i = 5: relatively prime to k; add (10 // 6) j-values: j=6 is the only solution

您看到它如何工作吗?

您可以进行一些其他检查,以通过线性和次线性因素来减少开销,但如上所述,我们仍将有一个受控的 O(n ^ 2)循环。

>