求出GCD = 1的最小子集的大小


10

这是2012年波兰大学生程序设计比赛的练习部分出现的问题。尽管我可以找到主要比赛的解决方案,但似乎在任何地方都找不到该问题的解决方案。

的问题是:给定一组的N不同的正整数不大于109中,找到大小m具有1以外没有公约数的最小子集的N为至多500,并且可以假设的溶液存在。

m9S|S|=10S1<g1<g2<...<g10i j S g 2 g 3g 10 g 2 g 3103 × 5 × 7 × 11 × × 29 = 3234846615 > 10 9gcd(gi,gj)=1ijSg2g3...g10g2g3...g103×5×7×11×...×29=3234846615>109,这是一个矛盾。

但是,即使这样,直接的蛮力仍然太慢。还有其他想法吗?


Whay不能g2=2
vonbrand 2013年

1g2>g12。不能是1,因为9-子集不能具有为1的GCDg1
Wakaka

Answers:


1

这个问题等效于以下问题,并且双向构造归约关系都很简单。

给定一个位向量列表,找到它们的最小数量,以使and所有结果均为。0()

然后,我们将集合覆盖率减小为。通过集合覆盖,我的意思是给定集合的列表,找到覆盖它们并集的最小集合数。S 1S k()S1,,Sk

我们将集合中的元素排序为。令,其中如果,否则为0。请注意,此函数是双射,因此具有反函数。 ˚F 小号= 1 - χ 一个1小号... 1 - χ 一个Ñ小号χ X小号= 1 X 小号a1,,anf(S)=(1χa1(S),,1χan(S))χx(S)=1xS

现在,如果我们在上求解,则解决方案是,然后是设置封面的解决方案。f S 1f S k{ f S b 1f S b m} { f 1S b 1f 1S b m}()f(S1),,f(Sk){f(Sb1),,f(Sbm)}{f1(Sb1),,f1(Sbm)}

因此,我认为这个问题正在测试一个人修剪搜索空间的能力。


您如何找到最小的顶点覆盖率?
Yuval Filmus

哦,nvm这个解决方案,它被设置为封面。
赵超

1
是的,但是我在想也许我们可以利用这种特殊情况的某些属性。例如,在这种情况下,集合都非常大,大小不小于。实际上,如果集合中的数字都很小,那么它们的大小将更大。此外,我们绝对可以找到涵盖所有内容的9套产品。无论如何,您如何建议我缩小搜索范围?n9
Wakaka 2013年

我看不出问题(*)等同于问题中给出的问题。一方面,问题中给出的问题可以保证所有整数均为,这对应于保证问题(*)中不出现的位向量的权重。109
DW

1

通过计算所有成对的gcd,删除重复项然后递归,可以相对有效地解决此问题。这是在重复执行之前删除重复项的操作,这样可以提高效率。

我将在下面更详细地说明该算法,但首先,它有助于定义二进制运算符。如果是正整数集,则定义小号ŤS,T

ST={gcd(s,t):sS,tT}.

注意和(在您的问题中); 通常,甚至会小于上述两个界限中的任何一个,这有助于提高算法的效率。还要注意,我们可以用计算通过简单的枚举进行gcd操作。| 小号Ť | 10 9小号Ť 小号Ť | S | × | T ||ST||S|×|T||ST|109STST|S|×|T|

使用该符号,这里是算法。令为数字输入集。计算,然后计算,然后,依此类推。找到最小使得但。然后,您知道最小的此类子集的大小为。如果您还想输出此类子集的具体示例,则通过保留反向指针,可以轻松地重构此类集。小号2 = 小号1小号1 小号3 = 小号1小号2 小号4 = 小号1小号3 ķ 1 小号ķ 1 小号ķ - 1 ķS1S2=S1S1S3=S1S2S4=S1S3ķ1个小号ķ1个小号ķ-1个ķ

这将是相对有效的,因为中间集的大小都不会增长到以上(实际上,它们的大小可能会小得多),并且运行时间大约需要 gcd操作。 500 × | S 1 | + | S 2 | + 109500×|小号1个|+|小号2|+

这是一种优化,可以进一步提高效率。基本上,您可以使用迭代加倍来找到最小的,使得中的。特别是,对于每个元素,我们跟踪的最集,其gcd为,大小为。(当删除重复项时,您将较小的子集来解决关系。)现在,与其计算九个集合的序列计算五个集合的序列,通过计算,然后,然后1 小号ķ X 小号š 1 X š 1s ^ 2S ^ 3s ^ 4... s ^ 9 s ^ 1S ^ 2S ^ 4s ^ 8š 9 š 2 = s ^ 1小号1 小号4 = 小号2小号2 小号ķ1个小号ķX小号一世小号1个X一世小号1个小号2小号3小号4小号9小号1个小号2小号4小号8小号9小号2=小号1个小号1个小号4=小号2小号2小号9 = 小号1 × 小号8 ķ [ 1 2 4 8 9 ] 1 小号ķ ķ 1 小号ķ 1 1 小号ķ 1 小号ķ小号8=小号4小号4,然后。转到时,找到第一个使得。一旦你找到使得,您可以立即停止:你能找到的最小的子集,其最大公因数通过查看相关联的子集。因此,您可以在达到设置为中的立即停止,如果找到较小的子集,则可以尽早停止。小号9=小号1个×小号8ķ[1个2489]1个小号ķķ1个小号ķ1个1个小号ķ1个小号ķ

这应该是省时和省空间的。为了节省空间,对于每个元素,您都不需要存储整个集合:足以存储两个反向指针(因此,您将gcd的的两个元素用于获取)和可选地,相应子集的大小。小号小号Ĵ XX小号ķ小号一世小号ĴX

原则上,您可以用任何其他加法链替换序列。我不知道其他加法链是否会更好。最佳选择可能取决于正确答案的分布以及集合的预期大小,这对我来说并不明确,但可能可以通过实验根据经验得出。小号ķ[1个2489]小号ķ

鸣谢:感谢KWillets提出了将数字子集与每个元素一起存储的想法,该想法允许提前停止。小号一世


我认为二进制搜索不是必需的;您可以在每个gcd中存储元素计数,并将其设置为每次加倍时的最小对和。
KWillets

好点,@ KWillets!谢谢你的好主意!我已将其合并到我的答案中。
DW

0

也许可以用另一种方式更快地查看它……小于的最大素数是31607,在2到31607之间的总数为3401个素数,不是一个很大的数。写下在质数上得到充分分解的每个数字,直到31607: 这里是1或大质数。然后,如果相应的向量是线性独立的(且它们的 s不同或均为1),则的集合就相对质数,并且您正在寻找矩阵的 ai=p n i 1 1 p n i 2 2PiPiainijP109

ai=p1ni1p2ni2Pi
PiainijP

与线性独立性有什么关系?向量和是线性独立的,但是当我们想要时,GCD为。1 0 1 0 0 0 1个1个1个01个000
Yuval Filmus 2013年

1
线性独立性似乎不起作用,但是我们可以以其他方式使用这种素分解。对于每个质数(在并且最多),将集合定义为所有不包含作为因数的数字(在给定集合中)的集合。现在的问题是找到数字的最集,使得对于每个,。这是命中布景问题,等同于布景问题。这是完成的,但是可能有一些实现足够快的实现。3401 p i 500 P i A p p B A p | 一个p| 1 Ñ Pp3401 p一世500 P一世一个pp一个p|一个p|1个ñP
polkjh 2013年

您能指导我一些可行的实现吗?到目前为止,我只能找到近似算法。谢谢!
Wakaka 2013年

调查报告同时研究了近似和精确的解决方案。回复评论时,请在评论中添加@ name-of-person。它将向该人发送通知。否则,他们甚至可能永远不会知道您的评论。
polkjh

-1

如果您能够找到gcd(S)= 1的子集,那么我总是可以从该子集中删除冗余元素,直到仅剩下2个元素,它们的gcd(S)=1。因此,我可以断言最小的一个子集将包含2个元素,否则将不存在。

现在,我们使用递归来解决此问题。让我们将数字数组分为2部分,一个包含n-1个元素,一个包含1个元素(最后一个元素)。这两个数字要么在前n-1个元素中,要么从第一个部分与最后一个元素成对出现一个元素。因此,我们能够解决这个问题

T(n)= T(n-1)+ O(n)时间。这意味着T(n)= O(n ^ 2)。


4
光盘61015=1个。您可以删除哪个元素?
瑞克·德克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.