4

有两个由大于 2 的整数组成的n 长度数组 (a和)。b

鉴于关于它们的某个条件为真(例如,它们不是互质数),我想在每一个回合中从每个数组(a[i]和)中删除一个整数。b[j](如果条件不成立,我会尝试删除另一个组合)

毕竟我想找到我可以实现的最大圈数(直到没有可能的组合可以删除符合条件的组合)。让我们称之为最佳转数。

我尝试使用搜索算法和PriorityQueue使用 Python 来解决这个问题:

def search(n, a, b):
    q = queue.PriorityQueue()
    encountered = set()
    encountered.add((tuple(a), tuple(b)))
    q.put((number_of_coprime_combinations(a, b), a, b))

    while q:
        cost, a, b = q.get()
        combs = not_coprime_combinations(a, b)

        if not combs:
            return n - len(a)

        for a, b in combs:
            if not (tuple(a), tuple(b)) in encountered:
                q.put((number_of_coprime_combinations(a, b), a, b))
                encountered.add((tuple(a), tuple(b)))

number_of_coprime_combinations(a, b)a返回给定数组和的可能的互质组合数b。这被用作两个数组的给定状态的成本。

def number_of_coprime_combinations(a, b):
    n = 0

    for idx_a, x in enumerate(a):
        for idx_b, y in enumerate(b):
            if is_coprime(x, y):
                n += 1

    return n

not_coprime_combinations(a, b)返回一个可能的状态列表,其中一个非互质组合已从a和中删除b

def not_coprime_combinations(a, b):
    l = []

    for idx_a, x in enumerate(a):
        for idx_b, y in enumerate(b):
            if not is_coprime(x, y):
                u, v = a[:], b[:]
                del(u[idx_a])
                del(v[idx_b])
                l.append((u, v))

    return l

>>> not_coprime_combinations([2,3],[5,6])
[([3], [5]), ([2], [5])]

问题是这种解决方案对于大整数的大型数组非常低效。所以我想知道是否有更好的解决方案来解决这个问题..

例子:

n = 4
a = [2, 5, 6, 7] 
b = [4, 9, 10, 12]

可以删除:

(2, 4)
(5, 10)
(6, 9)

这将导致最佳解决方案:

a = [7]
b = [12]

但是,如果要删除:

(6, 12)
(2, 10)

一个人会得到次优的解决方案:

a = [5, 7]
b = [4, 9]

该算法应始终得出最佳匝数(在本例中为 3)。

4

3 回答 3

3

据我所知,要解决这个问题:

  • 构造二部图 G,使得对于每个 Ai 和 Bj,如果 GCD(Ai,Bj) > 1,则 G 中有一条边 (Ai, Bj)。

  • 找到G的最大匹配

  • 匹配的基数是解决方案

我不知道如何更快地解决这个问题。

于 2013-07-08T13:12:40.713 回答
1

我知道你把这个问题放在哪里了。而你对这个问题的解决方案是错误的,因为它的 O(n^2) 和贪婪。n <= 10^5。2 > a,b < 10^9 来自数组

我认为在这个问题中你必须找到一些技巧。并且所有二分图中最大匹配的算法都将 TL。

于 2013-07-09T15:36:33.290 回答
0

假设:

  1. 函数is_coprime_pair(pair)已定义,接受长度为 2 的列表并返回True 一对素数
  2. a并且b是可迭代的组合
    导入迭代工具  
    not_coprimes = itertools.filterfalse(is_coprime_pair, itertools.product(a, b))

not_coprimes将保存所有不包含两个素数的对

于 2013-07-08T13:10:35.067 回答