最大化一个分区的GCD(最大公约数)之和?

时间:2019-06-08 05:54:05

标签: c++ greatest-common-divisor

给出一个正数数组。我想将数组分成2个不同的子集,以使它们的gcd(最大公约数)的总和最大。

示例数组:{6,7,6,7}

答案:两个必需的子集是:{6,6}{7,7};它们各自的gcd为6和7,它们的sum = 6+7=13;这是最大的gcd总和。

Gcd:{8,12}的Gcd为{4},因为4是除以8以及12的最大数。

注意:如果子集仅包含一个元素,则gcd(X)=X

我的方法:通过强制执行,我找到了数组的所有可能子序列,然后找到了最大和,但是如果输入大小大于30个数字,这将不起作用。我正在寻找一种更有效的方法。

额外:任何输入数字的最大大小为10 ^ 9,时间限制:-1s似乎不错,输入大小可能高达10 ^ 5

1 个答案:

答案 0 :(得分:11)

我认为这实际上是一个容易解决的难题。

首先,让我们忽略值出现多次的可能性。显然,最好将一个值的所有副本放在同一集合中,因为将其中一些副本移动到其他位置只会损害GCD(编辑:,除非只有一个不同的值)。因此,我们假设所有元素都是不同的。另外,令M为任何元素的最大值。

以这种方式思考:有一个简单的解决方案,即在一侧采用最高元素,而在另一侧采用其余元素。 “所有其他”-的GCD可能为1(当然可能更高),因此此解决方案为您提供M + 1。

任何具有多个不同元素的输入子集,其GCD都不能高于M / 2(因为必须将此除数乘以另一个除数(至少为2,才能得出原始值), (不高于M)。因此,编辑:最佳解决方案不能由两组分别具有多个不同元素的组组成。它必须是一个元素,而不是所有其他元素。

现在考虑两个最高元素,对于某些d具有值M和M-d。如果我们都不选择它们作为单例,则它们都在大组侧,这意味着该组最多具有d的GCD(因为如果g | M和g | M-d则为g | d);单身人士的贡献将不超过M-d-1。因此,总分最多为M-1,也就是说,比我们选择最高值时得到的分数小。 因此,在这种情况下,输入中的最高值或第二高(唯一)值必须位于其自己的集合中。

因此,您必须执行以下操作:

  • 处理只有一个不同值的琐碎情况。
  • 否则,获取2个最高元素;
  • 计算所有n-2个最低元素的GCD g_0。
  • 计算GCD的g_with_highest = GCD(g_0,M)和g_with_second_highest = GCD(g_0,M-d)。
  • 通过将M + g_with_second_highest与(M-d)+ g_with_highest进行比较来选择单例。