当前位置: 首页 > 知识库问答 >
问题:

等和子集

娄浩荡
2023-03-14

我想计算一个集合S存在多少对不相交的子集S1和S2(S1 U S2可能不是S),其中S1中的元素和=S2中的元素和。

假设我已经计算了所有可能的2^n子集的所有子集和。我如何找到有多少不相交的子集有相等的和。

对于一个和值a,我们能用有和a/2的子集的计数来解决这个问题吗?

例如:S={1,2,3,4}

以下是问题的链接:http://www.usaco.org/index.php?page=viewproblem2&cpid=139

共有1个答案

李永寿
2023-03-14

[编辑:修正愚蠢的复杂性错误。谢谢卡什!]

实际上,我相信您需要使用这里描述的O(3^N)算法来回答这个问题--O(2^N)分区算法只足够好,可以枚举所有不相交的子集对,这些子集的并集是整个基础集。

正如我链接到的答案中所描述的,对于每个元素,您基本上要决定是否:

  1. 将其放在第一组中,
  2. 将其放入第二组,或
  3. 忽略它。

考虑所有可能的方法,生成一个树,其中每个顶点有3个子:因此O(3^N)次。需要注意的一点是,如果您生成了一个解(S1,S2),那么您不应该也计算该解(S2,S1):这可以通过在您构建它们时始终保持两个集合之间的不对称来实现,例如,强制执行S1中的最小元素必须始终小于S2中的最小元素。(这种非对称强制有一个很好的副作用,就是将执行时间减半:))

如果您预期集合中会有许多小数字,那么还有另一种可能的加速可供您使用:首先,将列表中的所有数字按递增顺序排序。选择一些最大值m,越大越好,但要足够小,使您能够负担得起一个m大小的整数数组。现在我们将把数字列表分成两个部分,我们将分别处理:一个最多等于m的初始数字列表(这个列表可能相当小),以及其余部分。假设前k<=n个数字适合第一个列表,并将此第一个列表称为SK。原始列表的其余部分我们将称之为“S”。

第二,像往常一样处理余数(S'),但不是只记录具有相等和的不相交子集的数目,只要s1'-S2'<=m,就将d[abs(S1'-S2')]加到解的总数中。这是因为我们知道有许多方法可以从具有这种差分的前k个元素建立一对不相交的子集--对于每一个子集对(Sk1,Sk2),我们可以将Sk1或Sk2中较小的加到S1'或S2'中较大的,另一个加到另一个,最终得到一对具有相等和的不相交子集。

 类似资料:
  • 如何加快以下问题陈述的执行速度?我有一个正确的解决方案,通过每一个测试的小输入。但是,它超过了较大输入的时间限制。我当前的实现是数组大小的二次型。 你的答案应该是基于1的,这意味着数组的第一个位置是1而不是0。 实施

  • 我有这个问题来自hackerearth 给定一个N个整数的数组,C个卡和S个和。每一张卡片都可以用来将给定数组中的一个整数递增或递减1。查找给定数组中是否有任何子集(在使用任意数量的卡之后/之前)具有和S。 输入格式 输出格式 如果存在具有给定和的子集,则打印TRUE,否则打印false。 所以这基本上是子集和问题的一种变体,但我们不是要找出一个给定的具有和的子集是否存在,而是要找到从序列到中最大

  • 给定一个由N个元素组成的数组,找出数组的所有子集,其和等于目标值。 我已经看到了所有关于子集和的老问题,但没有一个对我有用。 输入的第一行包含数组的整数N大小 第二行包含由空格分隔的数组元素 目标和值 打印所有子数组(元素索引)。 我的代码对于小的输入工作得很好,但是对于N>150则需要很长的时间。有没有其他有效的算法可以做到这一点。请告诉我如何优化此代码以适应较大的输入。 这是我的代码 需要花费

  • 给定两个数组A和B,从A中选择一个子序列X,从B中选择Y,求和(X)应等于求和(Y)。我们必须找到选择这类子序列的方法。 数组中的元素数最多可以是100个值-100到100 我的方法是:生成两个数组的所有子序列,取它们的和,对于每个可能的和,将我们在数组A中找到的子序列的否与我们在数组B中找到的具有该和的子序列的否相乘。 这是非常低效的,因为生成的所有子序列都是O(2^100) 有人能帮我吗?我不

  • 我想检查是否可以将一个数组拆分为具有相同和的连续子数组。拆分数组还意味着删除数组的边框元素。 例如,要将其拆分为3个部分,我们需要删除到元素 通过删除这2个元素,就有3个相同和的连续子数组,和。 因此,如果可以将数组拆分为3个部分(等和)并删除它们之间的边界,则应返回true,否则应返回false。 返回的示例是。因为删除2个元素后,它将有4个元素,这些元素不能分组为3个相等的和 我不知道如何处理

  • 我一直在学习动态规划,我想通过打印出所有相加为一个数字的子集来进一步研究经典的子集和问题。我该怎么做呢?到目前为止,我知道如何根据是否存在相加的子集来打印true或false 如果可能,我想返回所有子集的数组。