【发布时间】:2018-05-10 05:30:12
【问题描述】:
所以,我在 topcoder 上发现了这个问题:
你的朋友卢卡斯给了你一个正整数序列 S。
有一段时间,你们两个和 S 玩了一个简单的游戏:卢卡斯会选择一个 数,并且您必须选择 S 的一些元素,使得 您选择的所有数字都是卢卡斯选择的数字。例如, 如果 S={2,1,2,7} 并且 Lucas 选择了数字 11,你会回答 2+2+7 = 11。
卢卡斯现在想通过选择一个数字 X 来欺骗你 将不是有效的答案。例如,如果 S={2,1,2,7},则不是 可以选择 S 中总和为 6 的元素。
给定 int[] S。找到最小的正整数 X 不能作为 S 的一些(可能所有)元素的总和。
约束: - S 将包含 1 到 20 个元素,包括 1 到 20 个元素。 - S 的每个元素都在 1 到 100,000 之间,包括 1 和 100,000。
但在编辑解决方案中已经写了:
如何找到最小的不可能和?嗯,我们可以试试 以下幼稚算法:首先尝试使用
x = 1,如果这不是 有效总和(使用上一节中的方法找到),那么我们 可以返回x,否则我们增加x,然后再试一次,直到 我们找到不是有效总和的最小数字。让我们找到迭代次数的上限,即
x的值我们需要在找到结果之前尝试。首先 全部,此问题中可能的最大总和为 100000 * 20(全部 数字是最大值 100000),这意味着 100000 * 20 + 1 将 不是不可能的值。我们可以确定最多需要2000001 步骤。这个上限有多好?如果我们在 20 个中的每个中有 100000 数字,1 不可能是一个总和。所以我们实际上需要一个 在这种情况下迭代。如果我们希望
1是一个可能的总和,我们应该 在初始元素中有1。然后我们需要一个2(否则我们会 只需要2次迭代),然后一个4(3可以通过添加找到1+2),然后是8(从5到7的数字可以通过添加一些来找到 2 的前 3 个幂),然后是16, 32, ...。事实证明 使用 2 的幂,我们可以很容易地进行需要很多的输入 迭代。使用 2 的前 17 次幂,我们可以覆盖到 前 262143 个整数。这应该是一个很好的估计 数量最多。 (我们不能在输入中使用2^18,小于 100000)。最多262143次,我们需要查询一个数字
x是否在集合中 可能的金额。我们可以在这里使用一个布尔数组。看起来 不过,即使是O(log(n))数据结构也应该足够快。
那么 100000*20 怎么可能给我们最大的可能呢?添加 S 的所有元素不会给我们最大的总和吗?我似乎根本无法理解整个解决方案。如何使用子集?有人可以向我解释整个解决方案吗?我没有得到这背后的数学。我是动态编程的新手。
谢谢你,如果我问了太多问题,我很抱歉。
【问题讨论】:
标签: c++11 subset dynamic-programming