【问题标题】:Volume of pile of cubes一堆立方体的体积
【发布时间】:2021-10-10 03:30:11
【问题描述】:

我正在尝试挑战。思路如下:

“你的任务是建造一座由 n 个立方体组成的建筑物。 底部的立方体的体积为 n^3,上面的立方体将 有 (n-1)^3 的体积,依此类推,直到顶部有 1^3 的音量。

给定建筑物的总体积 m。被给予 m 可以 你找到了你必须建造的立方体的数量?如果没有这样的 n 存在返回-1"

我显然看到了:

2³ + 1 = 9 = 3² 和 3 - 1 = 2

3³ + 2³ + 1 = 36 = 6² 和 6 - 3 = 3

4³ + 3³ + 2³ + 1 = 100 = 10² 和 10 - 6 = 4

5³ + 4³ + 3³ + 2³ + 1 = 225 = 15² 和 15 - 10 = 5

6³ + 5³ + 4³ + 3³ + 2³ + 1 = 441 = 21² 和 21 - 15 = 6

所以如果我想,如果我检查某个数字是平方根,我已经可以排除一些。然后我可以从 1 开始一个变量,从平方根中获取该值(增加它)。这些值最终会匹配,否则之前的平方根将变为负数。

所以我写了这段代码:

def find_nb(m):
    x = m**0.5
    if (x%1==0):
        c = 1
        while (x != c and x > 0):
            x = x - c
            c = c + 1

        if (x == c):
            return c
        else:
            return -1
    return -1

这不应该吗?我错过了什么? 例如,我失败了三分之一的样本集:10170290665425347857 应该是-1,在我的程序中它给出了 79863。

我是否遗漏了一些明显的东西?

【问题讨论】:

    标签: python optimization


    【解决方案1】:

    您遇到了浮点精度问题。也就是说,我们有

    In [101]: (10170290665425347857)**0.5
    Out[101]: 3189089316.0
    
    In [102]: ((10170290665425347857)**0.5) % 1
    Out[102]: 0.0
    

    因此内部分支被采用,即使它实际上不是正方形:

    In [103]: int((10170290665425347857)**0.5)**2
    Out[103]: 10170290665425347856
    

    如果您从 this question 借用许多整数平方根选项之一并验证 sqrt 平方给出原始数字,那么您的算法应该没问题,至少在我没有忽略某些极端情况的情况下。

    (顺便说一句:你已经注意到了关键模式。数字 1、3、6、10、15.. 非常有名,并且有自己的公式,你可以用它来解决是否存在这样的公式一个直接起作用的数字。)

    【讨论】:

      【解决方案2】:

      DSM 的答案是一个,但要添加我的两分钱来改进解决方案...

      Brilliant.org 中的这个表达式用于求和立方数:

      sum of k**3 from k=1 to n:
          n**2 * (n+1)**2 / 4
      

      这当然可以针对有问题的总体积来解决。这是四种解决方案之一(要求 n 和 v 都是正数):

      from math import sqrt
      
      def n(v):
          return 1/2*(sqrt(8*sqrt(v) + 1) - 1)
      

      但是这个函数也返回79863.0。现在,如果我们将所有从 1 到 n 的立方数相加,由于精度误差,我们会得到稍微不同的结果:

      v = 10170290665425347857
      cubes = n(v)    # 79863
      x = sum([i**3 for i in range(cubes+1)])
      
      # x = 10170290665425347857, original
      x  -> 10170290665425347856
      

      【讨论】:

        【解决方案3】:

        我不知道你的答案是否正确,但我有另一个解决这个问题的方法,它更容易

        def max_level(remain_volume, currLevel):
            if remain_volume < currLevel ** 3:
                return -1
            if remain_volume == currLevel ** 3:
                return currLevel
            return max_level(remain_volume - currLevel**3, currLevel + 1)
        

        您可以通过max_level(m, 0) 找到答案。它需要 O(n) 时间和 O(1) 内存。

        【讨论】:

        • 当您在10170290665425347857(这是 OP 必须处理的值之一)上尝试此解决方案时会发生什么?
        【解决方案4】:

        根据我的要求,我在 PHP 中找到了一个简单的解决方案。

        function findNb($m) {
            $total = 0;
            $n = 0;
        
            while($total < $m) {
                $n += 1;
                $total += $n ** 3;
            }
        
            return $total === $m ? $n : -1;
        }
        

        在 Python 中是:

        def find_nb(m):
            total = 0
            n = 0
            
            while (total < m):
                n = n + 1
                total = total + n ** 3
                
            return n if total == m else -1
        

        【讨论】:

        • 太好了,这就是答案:)
        • 这对于非常大的数字不是一个好的解决方案
        猜你喜欢
        • 2013-08-09
        • 1970-01-01
        • 2021-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多