可能的组合数量

时间:2008-09-12 18:50:34

标签: puzzle

如果我知道变量a,b,c,d,e有多少种可能的组合:

a+b+c+d+e = 500

并且它们都是整数且> = 0,所以我知道它们是有限的。

10 个答案:

答案 0 :(得分:11)

@Torlack,@ Jason Cohen:递归在这里是一个坏主意,因为存在“重叠的子问题”。即,如果您选择a作为1b作为2,则剩下3个变量,最多可加497个;您选择a2b1,即可到达同一子问题。 (随着数字的增长,这种巧合的数量会爆炸。)

攻击这样一个问题的传统方法是dynamic programming:自下而上构建一个表的子问题解决方案(从“1个变量的组合数加到0?”开始)然后通过迭代建立(“ n 变量的多少组合加起来 k ?”的解决方案是“的多少组合的解决方案的总和n-1 变量加起来 j ?“0< = j < = k )。

public static long getCombos( int n, int sum ) {
  // tab[i][j] is how many combinations of (i+1) vars add up to j
  long[][] tab = new long[n][sum+1];
  // # of combos of 1 var for any sum is 1
  for( int j=0; j < tab[0].length; ++j ) {
    tab[0][j] = 1;
  }
  for( int i=1; i < tab.length; ++i ) {
    for( int j=0; j < tab[i].length; ++j ) {
      // # combos of (i+1) vars adding up to j is the sum of the #
      // of combos of i vars adding up to k, for all 0 <= k <= j
      // (choosing i vars forces the choice of the (i+1)st).
      tab[i][j] = 0;
      for( int k=0; k <= j; ++k ) {
        tab[i][j] += tab[i-1][k];
      }
    }
  }
  return tab[n-1][sum];
}
$ time java Combos
2656615626

real    0m0.151s
user    0m0.120s
sys 0m0.012s

答案 1 :(得分:5)

您的问题的答案是2656615626

以下是生成答案的代码:

public static long getNumCombinations( int summands, int sum )
{
    if ( summands <= 1 )
        return 1;
    long combos = 0;
    for ( int a = 0 ; a <= sum ; a++ )
        combos += getNumCombinations( summands-1, sum-a );
    return combos;
}

在您的情况下,summands为5,sum为500。

请注意,此代码很慢。如果您需要速度,请缓存summand,sum对的结果。

我假设你想要数字>=0。如果您需要>0,请将循环初始化替换为a = 1,将循环条件替换为a < sum。我还假设你想要排列(例如1+2+3+4+52+1+3+4+5等)。如果您需要a >= b >= c >= d >= e,可以更改for循环。

答案 2 :(得分:2)

几个月前,我为爸爸解决了这个问题...延长你的使用时间。这些往往是一次性问题,所以我没有去寻求最可重复的......

a + b + c + d =总和

i =组合数量

        for (a=0;a<=sum;a++)
        {
            for (b = 0; b <= (sum - a); b++)
            {
                for (c = 0; c <= (sum - a - b); c++)
                {
                    //d = sum - a - b - c;
                    i++
                }
            }
        }

答案 3 :(得分:2)

这对于面试来说实际上是一个很好的问题,因为它很简单,你可以写在白板上,但很复杂,如果他们不仔细考虑就可以绊倒别人。此外,您还可以获得两个不同的答案,这些答案会导致实现完全不同。

订单事项
如果订单很重要,那么任何解决方案都需要允许任何变量出现零;因此,最直接的解决方案如下:

public class Combos {
    public static void main() {
        long counter = 0;

        for (int a = 0; a <= 500; a++) {
            for (int b = 0; b <= (500 - a); b++) {
                for (int c = 0; c <= (500 - a - b); c++) {
                    for (int d = 0; d <= (500 - a - b - c); d++) {
                        counter++;
                    }
                }
            }
        }
        System.out.println(counter);
    }
}

返回2656615626。

订单无关紧要
如果订单无关紧要,那么解决方案就不那么难了,因为除非已经找到了sum,否则你只需要确保零​​是不可能的。

public class Combos {
    public static void main() {
        long counter = 0;

        for (int a = 1; a <= 500; a++) {
            for (int b = (a != 500) ? 1 : 0; b <= (500 - a); b++) {
                for (int c = (a + b != 500) ? 1 : 0; c <= (500 - a - b); c++) {
                    for (int d = (a + b + c != 500) ? 1 : 0; d <= (500 - a - b - c); d++) {
                        counter++;
                    }
                }
            }
        }
        System.out.println(counter);
    }
}

返回2573155876。

答案 4 :(得分:1)

查看问题的一种方法如下:

首先,a可以是0到500之间的任何值。然后如果跟随b + c + d + e = 500-a。这通过一个变量减少了问题。递归直到完成。

例如,如果a为500,则b + c + d + e = 0,这意味着对于a = 500的情况,b,c,d和e的值只有一个组合。

如果a是300,那么b + c + d + e = 200,这实际上是与原问题相同的问题,只减少了一个变量。

注意:正如克里斯所指出的,这是一种实际上试图解决问题的可怕方式。

link text

答案 5 :(得分:0)

如果它们是真实数字然后是无限的...否则它有点棘手。

(好吧,对于任何实数的计算机表示,都会有一个有限的计数......但它会很大!)

答案 6 :(得分:0)

它有通用公式,如果
a + b + c + d = N
那么非负积分解的数量将为C(N + number_of_variable - 1, N)

答案 7 :(得分:0)

@Chris Conway的回答是正确的。我已经使用适合较小金额的简单代码进行了测试。

                    long counter = 0;
            int sum=25;

            for (int a = 0; a <= sum; a++) {
                for (int b = 0; b <= sum ; b++) {
                    for (int c = 0; c <= sum; c++) {
                        for (int d = 0; d <= sum; d++) {
                             for (int e = 0; e <= sum; e++) {
                           if ((a+b+c+d+e)==sum) counter=counter+1L;

                             }
                       }
                    }
                }
            }
            System.out.println("counter e "+counter);

答案 8 :(得分:0)

数学答案是504!/(500!* 4!)。

形式上,对于x1 + x2 + ... xk = n,非负数x1,... xk的组合数是二项式系数:(k-1) - 组合中包含(n + k)的组合-1)元素。

直觉是从(n + k-1)点中选择(k-1)个点,并使用两个选定点之间的点数来表示x1,... xk中的数字。

对于我第一次回答Stack Overflow的糟糕数学版表示抱歉。

Just a test for code block

Just a test for code block

    Just a test for code block

答案 9 :(得分:-1)

包括否定数据?无限的。

只包括积极因素?在这种情况下,它们不会被称为“整数”,而是“自然”。在这种情况下...我不能真正解决这个问题,我希望我能,但我的数学太生疏了。可能有一些疯狂的积分方式来解决这个问题。我可以为熟练的数学提供一些指导。

是x的最终结果, 范围从0到x, b的范围是0到(x - a), c的范围是0到(x - a - b), 等等,直到e。

答案是所有这些可能性的总和。

我正试图在Google上找到一些更直接的公式,但我今天的Google-Fu真的很低......