【问题标题】:Optimizing list comprehension to find pairs of co-prime numbers优化列表理解以查找互质数对
【发布时间】:2014-07-18 07:28:20
【问题描述】:

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

这是我的答案:

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

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

  • 1
  • 1

有没有更好的写法或者可以优化?

【问题讨论】:

  • 查找“相对素数”。
  • 记忆你的 gcd 函数
  • 由于您正在执行gcd 检查二次数对,因此您应该花时间预先计算所有数字的质因子集;那么找出两个数是否互质是一个简单的集合交集问题。
  • @MartijnPieters:重复的东西完全一样吗?计算相对质数的 a,b
  • 顺便说一句:我不会认为这是重复的,因为这个问题是关于测试 许多 对数字,因此可能需要考虑不同的算法。

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


【解决方案1】:

由于您需要为每个 pair 数字计算 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] 所有 因式 的数字>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 秒。这可能需要一些工作来适应您的实际问题,但我想这是一个好的开始。

【讨论】:

    【解决方案2】:

    根据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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-27
      • 1970-01-01
      • 2016-05-12
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      • 2011-08-30
      • 1970-01-01
      相关资源
      最近更新 更多