【问题标题】:Given a set of numbers,find the pair which has the least LCM(Lowest Common Multiple)给定一组数字,找到具有最小 LCM(最低公倍数)的对
【发布时间】:2017-03-27 19:20:10
【问题描述】:

我使用了这种方法。

  1. 找到所有可能的 nC2 对 n 个数字。
  2. 然后通过计算他们的 GCD 并将两个数字的乘积除以他们的 GCD 来单独找到他们的 LCM
  3. 还维护了一个变量,该变量包含迄今为止计算的最小 LCM 值并最终输出。

但是当数值非常大(~10^9)时,这种幼稚的方法似乎效率低下,因为 GCD 的时间复杂度将取决于数字的大小。同样对于非常大的 N 值也是不可行的。 有没有其他更好的方法来解决这个问题?

【问题讨论】:

  • n的最大范围是多少?
  • @Kaidul N 的约束是 2
  • 质数分解对 LCM 有什么影响?排序会有帮助吗?

标签: c algorithm math number-theory lcm


【解决方案1】:

我认为没有一种有效的算法。

你总是可以使用启发式和简单的方法,这肯定会解决这个问题。

平均而言,对于大多数数组,这对数字将类似于 a,b(a

因此,平均而言,LCM 不会很大并且与数组的元素相似。

所以,想法是对数组进行排序,然后按升序先尝试较小的 a,b。而当b > lcm_so_far .

谢谢

【讨论】:

  • 我不明白 _And when b > lcm_so_far - 然后呢? (不确定heuristics and simple which will definitely work。)
【解决方案2】:

对于大量的数字,欧几里得算法 (https://en.wikipedia.org/wiki/Euclidean_algorithm#Algorithmic_efficiency) 的有效实现来寻找 GCD 是我能想到的最佳途径。没有快速、通用的素数分解算法,因此使用它来减少问题无助于运行时间。我不知道有任何快速减少会对此有所帮助。

解决大N,我认为这是其他人一直在说的:

  1. 对数组进行排序
  2. 从最低值开始并计算 LCM(例如,对于 GCD 部分使用欧几里得算法):一旦剩余对的 LCM 不能小于目前找到的最佳值,则停止处理。请注意,对于排序集中的两个数字,b

可以对此进行其他优化(例如不在python中编写它:))但这证明了算法的改进:

import fractions

def lcm(a, b):
    return abs(a * b) / fractions.gcd(a, b)

def short_lcm(a):
    a = sorted(a)

    iterations = 0
    cur_lcm = lcm(a[0], a[1])
    first = a[0]
    second = a[1]
    for i in range(0, len(a)):
        #Best case for remaining pairs
        if i < len(a) - 1 and a[i + 1] >= cur_lcm: break

        for j in range(i + 1, len(a)): #Starting at i + 1 avoids duplicates
            if a[j] >= cur_lcm: break  #Best case for remaining pairs

            iterations += 1

            test = lcm(a[i], a[j])
            if test < cur_lcm:
                cur_lcm = test
                first = a[i]
                second = a[j]

    if iterations < 1: iterations = 1

    print("Lowest LCM pair is (%d, %d): %d. Found in %d iterations" % (
                first, second, cur_lcm, iterations))

def long_lcm(a):
    iterations = 0
    cur_lcm = lcm(a[0], a[1])
    first = a[0]
    second = a[1]
    for i in range(0, len(a)):
        for j in range(i + 1, len(a)):     #Starting at i + 1 avoids duplicates
            iterations += 1

             test = lcm(a[i], a[j])
            if test < cur_lcm:
                cur_lcm = test
                first = a[i]
                second = a[j]

    print("Lowest LCM pair is (%d, %d): %d. Found in %d iterations" % (
                first, second, cur_lcm, iterations))

if __name__ == '__main__':
    from random import randint
    import time

    a = [randint(1, 1000) for r in xrange(100)]

    #Only print the list if it's relatively short
    if len(a) < 20: print a

    #Try all pairs
    start = time.clock()
    long_lcm(a)
    print "Slow version time: %f\n" % (time.clock() - start)

    start = time.clock()
    short_lcm(a)
    print "Fast version time: %f" % (time.clock() - start)

【讨论】:

  • 嘿安德鲁。你能告诉我可以对此进行哪些改进
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 1970-01-01
  • 2020-07-11
  • 1970-01-01
相关资源
最近更新 更多