【问题标题】:OEIS A002845: Number of distinct values taken by 2^2^...^2 (with n 2's and parentheses inserted in all possible ways)OEIS A002845:2^2^...^2 取的不同值的数量(以所有可能的方式插入 n 2 和括号)
【发布时间】:2012-07-31 18:06:38
【问题描述】:

我正在寻找一种相当快的算法来计算 OEIS 序列 A002845 的项。让我在这里重申它的定义。

让 ^ 表示求幂运算符。考虑 2^2^...^2 形式的表达式,其中有 n 2 个括号以所有可能的方式插入(可能的括号数由 Catalan numbers 给出)。其中一些表达式将具有相同的值,例如 (2^2)^2=2^(2^2)。我们对给定 n 的不同值的数量感兴趣。

通过直接计算这些表达式有一个明显的蛮力解决方案,但很明显,即使对于相对较小的 n,所需的时间和空间也会很快超过所有合理的限制。我对这个问题的多项式时间解决方案感兴趣。

【问题讨论】:

标签: algorithm numbers sequence combinatorics exponent


【解决方案1】:

仅表示迭代基数 2 中的数字:Num 有一个(可能为空)x1,...,xp 类型为 Num 的不同子代列表,因此 Num([x1,...,xp]) == 2^x1 + ... + 2^xp

这定义了一种写入非负整数的独特方式;请记住对指数进行排序,以便比较有意义。等式:

  • 2^x + 2^x == 2^(x+1) == Num([x+1])
  • 2^x + 2^y == Num([x,y])x != y
  • (2^2^x)^2^y == 2^2^(x+y) == Num([Num([x+y])])

连同加法的结合性/交换性允许您添加任意数字并计算 x^y 以获取 2^2^k 形式的数字;这类数字包含 2(其中 k=0)并且在^ 下封闭,因此这保证了我们需要操作的每个数字都是这种形式。

此外,上面定义的等式永远不会增加树中节点的数量,因此所有Num 的大小都是O(n)

所以时间复杂度实际上是O(C * n^k),它在 C 中是准线性的(C 是第 (n-1) 个加泰罗尼亚数)。

【讨论】:

  • 我认为这个答案最接近问题的解决方案。我很高兴将赏金奖励给它的作者。
【解决方案2】:

我认为这里最好的解决方案涉及动态编程,这是一个难以掌握的概念,但如果操作正确,将非常有效。这个想法是通过记住您已经完成的计算结果,然后使用这些知识将问题拆分为更简单问题的子集,从而最大限度地减少您必须进行特定计算的次数。

例如,在您的 2^(2^2) = (2^2)^2 示例中,我们现在可以将其记住为等于 16 的值的两件事。到 2^(2^(2^2)) = 2^((2^2)^2) 我们可以很快将其中的每一个识别为 2 ^ 16,计算一次,我们现在有两个新方程添加到我们永远不必再次计算的值列表中。

这似乎没有多大帮助,但是,当您最终得到一连串很长的带括号的问题,甚至更长的等价集时,它会为您节省时间和复杂性,因为对于一个非常长的计算计算机可以处理非常大的数字。下面是伪代码,抱歉,这真的是很宽泛的伪代码,这个问题很粗糙,所以我不想写出一个完整的算法。只是更详细地概述了这个概念

 sortedEquivalencyVector;  //Sorted greatest first, so we are more likely to se longest matches

 function(expression)

    if(portion of expression exists)  //Remember, you can only do this from the end of the expression in toward the middle!
         replace value at end of expression that matches with its already computed value

    if(simplified version exists in vector) add original expression to vector
    else compute value and add it to the vector
 end

【讨论】:

  • 尽管如此,即使不重新计算,值也会增长得非常快——即使计算一次也需要大量的时间和内存。
  • 是的,但是仅仅因为一个问题很困难并不意味着它是可以避免的......这个想法是将长计算的数量限制在最低限度。如果您有一个完全避免这样做的答案,为什么不提供呢。
  • 我没有答案,我也没有声称我有。但是您的帖子也不是答案。您只是给出了一些明显的建议,这些建议已经在对该问题的评论中给出,它们对解决解决方案的主要障碍没有帮助 - 巨大的数字。没什么私人的,但我只是觉得这个问题很有趣,值得一个真正的答案。
  • 我其实完全不同意。问题不是针对计算 2^2^2^2^2^2 的值,而是针对计算所有括号组合的复杂性。一个是针对堆栈溢出的算法问题,另一个是数学问题,这不是关于“我对这个问题的多项式时间解决方案感兴趣”的问题。表明他更关心整体解决方案的复杂性,而不是简化一个实例的计算。
  • 有用的想法,但不幸的是,没有答案。它不能用于直接计算有问题的序列。
【解决方案3】:

一种比蛮力好得多的方法(但诚然仍然很昂贵)是在第一篇链接论文中使用“标准形式”的概念。给定一个n,生成每个标准形式的度n,评估它,并将所有值保存在一个集合中。最后,检查集合的大小。

标准形式的语法是

S -> (2 ^ P)
P -> (S * P)
P -> S
S -> 2

您以S 开头,最后您应该有n 终端(即2s)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-19
    • 2014-03-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多