简体   繁体   English

总计为A的N个整数的不同组的数量

[英]number of different groups of N integers that sum up to A

I want to calculate the number of different ordered groups of N integers so that the elements of each group sums up to A 我想计算N个整数的不同有序组的数量,以便每个组的元素总和为A.

For instance: if N = 3 and A = 3 the result should be 10: 例如:如果N = 3且A = 3,结果应为10:
1 = [3, 0, 0] 1 = [3,0,0]
2 = [2, 1, 0] 2 = [2,1,0]
3 = [1, 2, 0] 3 = [1,2,0]
4 = [0, 3, 0] 4 = [0,3,0]
5 = [2, 0, 1] 5 = [2,0,1]
6 = [1, 1, 1] 6 = [1,1,1]
7 = [0, 2, 1] 7 = [0,2,1]
8 = [1, 0, 2] 8 = [1,0,2]
9 = [0, 1, 2] 9 = [0,1,2]
10 = [0, 0, 3] 10 = [0,0,3]

the way I did it was by brute-force: 我这样做的方式是蛮力:

public static int calc(int a, int n){
    if (n <= 1 || a == 0) return 1;

    int sum = 0;
    for (int i=0; i<=n; i++)
        sum += calc(a - i, n - 1);

    return sum;
}

i suspect that there can be a better way (some mathematical calculation that I missing..) is there? 我怀疑可能有更好的方法(我错过了一些数学计算......)吗?

EDIT In the original question i forgot to take into consideration the order 编辑在原始问题中,我忘了考虑订单

This is combinatorial composition of A into N parts (including zero parts). 这是A到N部分(包括零部分)的组合成分 Number of compositions for pair (A, N) is equal to C(A + N - 1, A), where C() is combination number aka binomial coefficient. 对(A,N)的组成数等于C(A + N-1,A),其中C()是组合数,即二项式系数。 See the same formula here and here 这里这里看到相同的公式

Imagine big segment of length A . 想象一下长度为A大段。 And imagine N-1 ordered separators, dividing the segment into parts. 并想象N-1有序分隔符,将分段分成几部分。 Hence, each part is a summand while entire segment is a sum. 因此,每个部分是一个加数,而整个部分是一个总和。

Ergo, all you need is just to provide algorithm to enumerate separators location. 因此,您只需提供算法来枚举分隔符位置。

First separator you can put into any of N+1 positions P_0={0,1,...N} 可以放入N+1位置的第一个分隔符P_0 = {0,1,... N}

Second separator can go into any of P_1={P_0,...N} 第二个分隔符可以进入P_1 = {P_0,... N}中的任何一个

And so on. 等等。

You can use recursion to implement this. 您可以使用递归来实现此功能。

I am sure there is a mathematical calculation to answer this, but since this is a programming Q&A, I'll tell you how to make your program give the answer faster: you can use memoization . 我确信有一个数学计算来回答这个问题,但由于这是一个编程问答,我会告诉你如何让你的程序更快地给出答案:你可以使用memoization

Currently, your program re-calculates the answer to calc(a, n) every time. 目前,您的程序每次都会重新计算calc(a, n)的答案。 However, the answer can be calculated once, because it does not change in subsequent invocations. 但是,答案可以计算一次,因为它在后续调用中不会更改。 Add a 2D array for the result of calc(a,n) , initialize with -1 , and use it to look up results before calculating them to save a lot of time re-calculating the same numbers over and over: calc(a,n)的结果添加一个2D数组,用-1初始化,并在计算结果之前使用它来查找结果,以节省大量时间反复重复计算相同的数字:

private static int[][] memo = new int[30][30];
static {
    for(int i = 0 ; i != 30 ; i++)
        for(int j = 0 ; j != 30 ; j++)
            memo[i][j] = -1;
}
public static int calc(int a, int n){
    if (n <= 1 || a == 0) return 1;
    if (memo[a][n] > 0) return memo[a][n];
    int sum = 0;
    for (int i=0; i<=n; i++)
        sum += calc(a - i, n - 1);
    return (memo[a][n] = sum);
}

For enumeration: Use the formula given in other solutions above, WAY MORE EFFICIENT. 对于枚举:使用上面其他解决方案中给出的公式,更加高效。 You never want to actually generate a full set of n-integer compositions unless it is required. 除非需要,否则您永远不想实际生成一整套n整数合成。 They carry intractable properties especially if you want to only total them, not generate them. 它们具有难以处理的属性,特别是如果您只想要总计它们,而不是生成它们。 Generating them is another problem... 生成它们是另一个问题......

For generation: Use a loopless algorithm... There are numerous O(1)-per gray code sequence results out there. 用于生成:使用无环算法...有很多O(1) - 灰色代码序列结果。 There are very few variations of restricted integer compositions out there that do not have or can have loopless algorithms. 限制整数组合的变化非常少,没有或没有无循环算法。 Many algorithms in this class of problems for integer compositions, most of which are very specific but there are plenty modern loopless algorithms which exist for this specific problem. 在整类组合的这类问题中有许多算法,其中大多数是非常具体的,但是对于这个特定问题存在大量现代无循环算法。 Super efficient. 超级高效。 Brute force is never the way to go with this problem unless you got a lot of parallel computing at your disposal. 除非你有大量的并行计算功能,否则蛮力绝不是解决这个问题的方法。 Google or Google Scholar is at your disposal! Google或Google Scholar随时为您服务! :D :d

Hope this helps! 希望这可以帮助!

I found another solution, just with recursion and without separators: 我找到了另一个解决方案,只是递归和没有分隔符:

public class App201210121604 {

public static Vector<int[]> split(int sum, int count) {

    if( sum < 0 ) {
        throw new IllegalArgumentException("Negative sum is not allowed");
    }

    Vector<int[]> ans = new Vector<int[]>();

    // "reserved" end of recursion
    if( count <= 0 ) {
        // nothing to do
    }

    // end of recursion
    else if( count == 1 ) {
        ans.add(new int[] {sum});
    }

    // body of recursion
    else {
        // for each first summand from 0 to summ
        for(int i=0; i<=sum; ++i) {

            // do a recursion to get the "tail"
            for(int[] tail : split(sum-i, count-1)) {

                int[] group = new int[count];
                group[0] = i;
                System.arraycopy(tail, 0, group, 1, count-1);

                ans.add(group);
            }
        }
    }

    return ans;
}

public static void main(String[] args) {

    Vector<int[]> ans = split(8, 4);

    for(int[] group : ans) {
        for(int i=0; i<group.length; ++i) {
            if( i>0 ) System.out.print("+");
            System.out.print(group[i]);
        }
        System.out.println("");
    }
}

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 找出将 n 表示为两个有边界整数之和的方法的数量 - Find the number of ways to represent n as a sum of two integers with boundaries 查找相加为整数的不同整数对的数量 - Finding the number of distinct pairs of integers that sum up to an integer 如何计算小于n且总和大于n * 2的3个整数的组合数? - How to calculate the number of combinations of 3 integers less than n whose sum is greater than n * 2? 当输入的整数个数未知时,扫描并求和所有输入的整数 - Scan and sum up the all integers input when the number of integers of input is unknown 查找大小为N的数字的组合,这些数字的和等于给定的数字 - Finding a combination of numbers of size N that sum up to a given number 确定数据集中的任意 3 个整数是否在 O(n^2) 时间内与目标值相加 - Determine whether any 3 integers from a data set sum up to a target value in O(n^2) time 将N个具有不同值的项目分配到组中,仅当组中的项目总和为D时才有效 - Distributing N items with different values into groups which are only valid if sum of items in the group is D 获取具有旧数字1 +(1 + 2)+(1 + 2 + 3)+…+(1 + 2 + 3 +…+ n)的整数和 - Get sum of integers with old numbers 1 + (1 + 2) + (1 + 2 + 3) + … + (1 + 2 + 3 + … + n) n 个整数扫描器的总和 - Sum of n-amount of Integers Scanner 给定2d整数数组,找到一个递归地总结给定数字的路径 - Given 2d array of integers, find a path that sum up to a given number recursively
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM