给定数组A1,A2。 。 。 AN数组的最大子集的大小是多少,这样子集中的每对元素都是互质的。
示例:设N = 5,数组为[2 3 2 3 2],则答案为2
说明:最大的子集将采用A [0],A [1],A [2]中的一个并取A [3],A [4]中的一个。
N可以达到最大值50.如何处理这个问题?
答案 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
都认为如果x
和y
是互质的,那么x0
和y
。由于您只对子集的大小感兴趣,因此您可以将每个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
:这是有效的,因为如果x
是y
,它将包含所有y
的除数,甚至更多。因此,如果存在包含x
的解决方案,则该解决方案将无法使用y
进行扩展,但如果我们将x
替换为y
,则该解决方案将有效。