由于问题得到纠正而进行了大量编辑
考虑函数 f(x,y),它给出了您可以在 x 次投掷和 y 次死亡的限制下测试的楼层数。如果第一次投掷导致死亡,则剩下 x-1 次投掷和 y-1 次死亡,因此您可以检查 f(x-1, y-1) 个楼层。如果第一次投掷没有导致死亡,那么您还有 x-1 次投掷和 y 次死亡,因此您可以检查您投掷的楼层上方的 f(x-1,y) 个楼层。因此我们有递归 f(x,y) = f(x-1, y-1) + f(x-1, y) + 1。基本条件是 f(x,0) = 0(因为如果你即使投掷一次也有死亡的风险,所以你不能投掷,甚至不能检查一楼),并且 f(1,x) = 1 其中 x>0 (你必须从一楼,因为如果你从更高的楼层扔掉并死亡,你没有结果)。
现在,考虑 xCr 的函数 g(x, y) = SUM 10 给出 1C1 = 1。所以只需要检查 g 是否满足递归。
g(x-1, y-1) + g(x-1, y) + 1 = SUM 1x-1Cr + SUM 1x-1Cr + 1
g(x-1, y-1) + g(x-1, y) + 1 = SUM 2x-1Cr-1 + SUM 1x-1Cr + 1
g(x-1, y-1) + g(x-1, y) + 1 = SUM 2x-1Cr-1 + SUM 1x-1Cr + x-1C0子>
g(x-1, y-1) + g(x-1, y) + 1 = SUM 1x-1Cr-1 + SUM 1x-1Cr
g(x-1, y-1) + g(x-1, y) + 1 = SUM 1x-1Cr- 1 + x-1Cr)
g(x-1, y-1) + g(x-1, y) + 1 = SUM 1xCr)
g(x-1, y-1) + g(x-1, y) + 1 = g(x, y)
QED
事实上,这可以通过将其视为组合问题直接推导出来。如果我们充分利用所获得的每一点信息,那么每个可能的生存或死亡序列对应于不同的最大底线。例如。三掷,一次允许死亡,可能性是死亡;生存-死亡;生存-生存-死亡;或生存-生存-生存。但是,我们必须不考虑没有死亡的情况,因为在那种情况下,我们还没有确定下限。因此,如果我们有 x 次投掷和 y 次允许死亡,我们可以得到从 1 到 y 的实际死亡人数 r,并且对于其中的每一个,我们都有 xCr 可能序列。 (如果 r = y,那么在第 yth 次死亡之后的任何“幸存者”实际上都是“未投掷”)。
jdmetz 对 F 的解决方案包括评估 g(D, B)。它不能在 O(min(D, B)) 时间内完成,因为该总和没有封闭的超几何形式(可以使用 Gosper 算法证明这一事实)。
附录
事实上,原始问题的所有三个部分都可以在线性时间内完成(假设乘法和算术是恒定时间的运算,我们到目前为止 - 不正确,但我们将把它放在一边)。 jdmetz 解决方案中的 O(n lg n) 操作是找到最小的 D 使得 f(D, B) >= F。
如果我们将原始递归 f(D, B) = f(D-1, B-1) + f(D-1, B) + 1 与 g 形式的项差异相结合,f(D , B) = f(D, B-1) + DCB 我们得到 f(D, B) = 2 * f(D-1, B) + 1 - D-1CB。然后我们可以使用 aCb = a-1Cb * a / (a - b) 来从 1 循环遍历 D。
private static int d_opt(final long f, final int b)
{
int d = 0,dCb = 0;
长 f_db = 0;
而 (f_db