【问题标题】:total sums with n number of digitsn 位数的总和
【发布时间】:2015-01-27 23:13:15
【问题描述】:

所以我有点难为你了。我需要编写一个函数,该函数接受一个数字(称为 K)并输出 n 个数字,如果这些数字 == K,则总和。

例如,如果我给这个函数 (100,3) 它将输出 [1,2,97], [1,3,96], [1,4,95]... [97,1, 2]

我已经计算出三位数的函数:

k = 100
r = []
0.upto(k/2) do |a|
    (a+1).upto(k/2) do |b|
        c = k-(a+b)
        r << [a,b,c]
    end
end

如何编写这个需要 n 位数的函数?

【问题讨论】:

  • 如果您不要求解决方案是唯一的(除了订单),那么您所拥有的就不会真正起作用。您显示的[97,1,2] 示例解决方案不能与您拥有的循环一起发生。前两个加数的最大值为50。而且你的要求不明确。它应该输出所有个可能的加数组合吗?加数是否必须大于 0?
  • 确认,你完全正确。这是为了找到加起来为 k 的唯一附加项。
  • 有无限多的数字加起来等于任何给定的数字。你想一一列举吗?
  • 目标是找到 N 个加起来为 k 的唯一加数。
  • 如果您希望有一个有限的解决方案,您将需要添加一些约束。您忽略的最可能的约束是加数必须全部 >= 0,即不允许负数。

标签: ruby function loops math nested


【解决方案1】:

这可能不是世界上最好的解决方案(所需的内存随着O(k^3) 而增长),但它是一个解决方案。欢迎提出改进建议。

您可能有兴趣阅读有关 integer partitions 的信息,这就是我们在这里计算的内容。

您正在寻找一个函数f(k,n),它将计算将数字k 精确划分为n 部分的方法数。部分问题是很难判断何时计算分区两次。

我将通过使用另一个函数g(k,n,s) 来解决这个问题,该函数计算将数字k 划分为n 部分的方式的数量允许的最大值是 s .例如,我们不计算g(100,3,60) 中的分区(90,8,2)(64,20,16),因为它们使用的值大于s=60

g(k,n,s) = f(k,n)s&gt;=k 时(即我们不对分区中允许的值设置最大值)。


关于g(k,n,s)的一些事实:

  • k==n 暗示 g=1,因为将 k 划分为 k 部分的唯一方法是使用所有 1s(因此 s 是无关紧要的,因为我们使用了可能的最低数量)
  • n&gt;k 暗示 g=0 因为我们不能将 k 划分为多个 k 部分
  • s==1 意味着 g=1 如果 k==ng=0 否则,因为放置最大值 1 只允许将 k 分区到 k 部分(全部)
  • n==1 意味着 g=1 如果 s&gt;=kg=0 否则,因为 kn=1 部分的唯一分区要求我们在分区中使用 k 本身
  • s&lt;RoundUp(k/n) 暗示 g=0 因为我们不能使用小于 k/n 的值将 k 划分为 n 部分;例如,我们不能仅使用小于 25 的值对 100 int o 4 进行分区。
  • s&gt;k-n+1 暗示 g(k,n,s) = g(k,n,s-1) 因为在 k-n+1 之后增加最大值 s 不会添加任何新分区;例如,1003 部分的任何分区都不会包含大于 100-3+1 = 98 的数字
  • g(k,n,s) = g(k,n,s-1) + g(k-s,n-1,s) 在其他情况下。这只是将使用值s 的所有分区添加到我们使用最大值s-1 计算的所有先前分区中

现在我只需选择最大数 K 并将所有这些事实放入嵌套的 for 循环中并推导出 g(k,n,s) 的每个值。要获得f(k,n),我只需要找到g(k,n,k)


这是算法,不适合大K

g = (K by K by K) array of all zeros

for k = 1:K
    for n = 1:K
        for s = 1:K

            if (k==n)
                val = 1;
            else if (n>k)
                val = 0;
            else if s==1
                val = int(k==n);
            else if n==1
                val = int(s>=k);
            else if s<RoundUp(k/n)
                val = 0;
            else if s>(k-n+1)
                val = g(k,n,s-1);
            else
                val = g(k,n,s-1) + g(k-s,n-1,s);
            end

            g(k,n,s) = val;

        end
    end
end

对于f(100,3) = g(100,3,100),我得到833 唯一分区,如果您使用蛮力方法,您可以看到它是正确的。如有错误请指出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多