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))
答案 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*j
,i
和j
必须包含必需数量的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)循环。
>