最大互质子集

时间:2015-02-14 16:21:21

标签: algorithm

给定数组A1,A2。 。 。 AN数组的最大子集的大小是多少,这样子集中的每对元素都是互质的。

示例:设N = 5,数组为[2 3 2 3 2],则答案为2

说明:最大的子集将采用A [0],A [1],A [2]中的一个并取A [3],A [4]中的一个。

N可以达到最大值50.如何处理这个问题?

2 个答案:

答案 0 :(得分:3)

因为对于所有i您知道1 ≤ Ai ≤ 50,您可以先过滤输入,然后强制执行。

您总是可以为子集选择所有素数,因为每个素数至少与该素数的任何倍数一样好(对于给定的素数p,如果整数x与某些素数相互作用k * x,那么它也与p互译。之后,您可以删除所有选定素数的倍数,因为它们不能出现在结果中。

对于更多过滤,请考虑以下事项:每个整数都可以唯一写入素数的乘积,例如:

 2 = 21
 6 = 2131
40 = 2351

对于整数x,让我们为相应的整数写x0,其中所有素因子都有幂1.例如,如果是x = 40 (2351),那么x0 = 10 (2151)。我们不需要考虑具有幂>1的质数,因为对于每个整数y都认为如果xy是互质的,那么x0y。由于您只对子集的大小感兴趣,因此您可以将每个x替换为x0

只有14个低于50的数字没有素数且没有素数因素>1

6, 10, 14, 15, 21, 22, 26, 30, 33, 34, 35, 38, 39, 42

减少的数字x0是此集合的成员。由于数量很少,你可以简单地使用暴力来找到最大的子集。

答案 1 :(得分:1)

您可以做很多事情来优化这种强力解决方案:

生成包含0和1的所有长度为2^N的字符串,并且对于每个字符串,请考虑数组中与1的位置对应的数字子集。所以:

10010

你要考虑:

2 3

根据您的限制,这可能是有效的,也可能不是。如果它无效,那么您添加到其中的任何其他数字也会导致无效的设置。

因此,您可以优化的一件事是:每当您在字符串中生成1时,请检查它对应的数字是否与先前生成的数字相对应。如果是,请停止生成并回溯。

另一件可能有帮助的事情就是对数组进行排序:这可能有助于将非互文数据放在一起(特别是如果您的值范围很小),从而帮助您缩短搜索时间。

为了让自己相信我上面所说的可行,请认识到50以下的素数是:

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 49

所以只有16。这意味着这是您将要找到的这样一个子集的最大长度,因此尝试找到更长的子集是没有意义的。第一个优化将有助于将生成的子集限制为最多16个。

接下来,对于原始数组x, y中的任何一对x mod y = 0,您可以从数组中删除x:这是有效的,因为如果xy,它将包含所有y的除数,甚至更多。因此,如果存在包含x的解决方案,则该解决方案将无法使用y进行扩展,但如果我们将x替换为y,则该解决方案将有效。