优化列表理解以找到成对的素数

时间:2014-05-28 21:43:24

标签: python list tuples list-comprehension greatest-common-divisor

  

给定A,B打印对(a,b)的数量,使得GCD(a,b)= 1且1 <= a <= A且1 <= b <= B。

以下是我的回答:

return len([(x,y) for x in range(1,A+1) for y in range(1,B+1) if gcd(x,y) == 1])

我的答案适用于小范围但如果范围增加则需要足够的时间。 比如

  • 1&lt; = A&lt; = 10 ^ 5
  • 1&lt; = B&lt; = 10 ^ 5

有没有更好的方法来写这个或者这可以优化吗?

2 个答案:

答案 0 :(得分:3)

根据wikipedia,这应该产生所有的互质:

from collections import deque

def coprimes():
    tree = deque([[2, 1], [3, 1]])
    while True:
        m, n = tree.popleft()
        yield m, n
        tree.append([2 * m - n, m])
        tree.append([2 * m + n, m])
        tree.append([m + 2 * n, n])

这不是最快的算法,但最容易理解。另请参阅http://en.wikipedia.org/wiki/Farey_sequence

答案 1 :(得分:3)

由于您需要计算每个数字是否gcd == 1,您应该预先计算所有素因子集。这样,您可以稍后通过检查其素因子集的交集来非常快速地确定两个数字是否是互质的。我们可以通过sieve-like方法快速完成此操作。

factors = [set() for n in range(N)]
factored = collections.defaultdict(set)
for n in range(2, N):
    if not factors[n]:           # no factors yet -> n is prime
        for m in range(n, N, n): # all multiples of n up to N
            factors[m].add(n)
            factored[n].add(m)

在此之后,factors[n]将包含n(duh)的所有主要因素,以及factored[n]所有 因子< em> by n。现在这将派上用场,因为否则我们仍然需要检查多达10,000 x 10,000对数字,这在Python中仍然相当慢。但是,结合使用factorsfactored集合,我们现在可以通过消除与n共享素数因子的数字,快速找到给定数字的所有联合素数。

for n in range(1, N):
    coprimes = set(range(1, N))  # start with all the numbers in the range
    for f in factors[n]:         # eliminate numbers that share a prime factor
        coprimes -= factored[f]
    print "%d is coprime with %r others" % (n, len(coprimes))

对于N == 100,结果看起来似乎合理,对于N == 10000,我的计算机上需要大约10秒钟。这可能需要一些工作来适应您的实际问题,但我认为这是一个良好的开端。

相关问题