需要高效实施以下公式?

时间:2011-11-05 06:10:06

标签: java c++ c

我一直在尝试实施以下公式

公式如下

求和(从i = 1到i = K)(M选择i)* i! * StirlingNumberOfSeconfType(N,i)

用于约束

1≤N≤1000 1≤M≤1000000 1≤K≤1000

但是我没有得到大量输入的结果,任何人都能为我提供公式的有效实施吗?

2 个答案:

答案 0 :(得分:1)

如果在gcc上使用C或C ++,可以尝试使用double(或“long double”)以避免因较大的结果而失败。

编辑:更仔细地阅读问题

高效斯特林计算第二个数字计算(问题标题具有误导性我知道但是阅读它):https://mathoverflow.net/questions/34151/simple-efficient-representation-of-stirling-numbers-of-the-first-kind

使用http://gmplib.org/来避免溢出。

答案 1 :(得分:0)

我最近使用BigInteger实现了这一点。我的方法是静态的,因为它是我项目的实用程序类的一部分,可以随意更改它们。

来自这里的解释:

Stirling Numbers of the second kind

Binomial Coefficient

进行舍入以消除变量限制的不准确性。

注意:只有在必要时才应使用BigInteger。我不得不计算可能的最大长度数组中可能的组合数,因此我认为BigInteger在我的计算中需要精确度。如果您不需要此准确度,请切换为长。

评论应解释代码:

/**
 * calculates the sterling number of {n k}
 *
 * @param n
 * @param k
 * @return
 */
public static BigDecimal SterlingNumber(int n, int k) {
    //return 1 or 0 for special cases
    if(n == k){
        return BigDecimal.ONE;
    } else if(k == 0){
        return BigDecimal.ZERO;
    }
    //calculate first coefficient
    BigDecimal bdCoefficient = BigDecimal.ONE.divide(new BigDecimal(UtilityMath.factorial(k)), MathContext.DECIMAL64);

    //define summation
    BigInteger summation = BigInteger.ZERO;
    for (int i = 0; i <= k; i++) {
        //combination amount = binomial coefficient
        BigInteger biCombinationAmount = UtilityMath.getCombinationAmount(k, i, false, false);
        //biN = i^n
        BigInteger biN = BigInteger.valueOf(i).pow(n);

        //plus this calculation onto previous calculation. 1/k! * E(-1^(k-j) * (k, j) j^n)
        summation = summation.add(BigInteger.valueOf(-1).pow(k - i).multiply(biCombinationAmount).multiply(biN));
    }

    return bdCoefficient.multiply(new BigDecimal(summation)).setScale(0, RoundingMode.UP);
}

/**
 * get combinations amount where repetition(1:1) is not allowed; and Order
 * does not matter (both 1:2 and 2:1 are the same). Otherwise known as
 * Bionomial coefficient [1] .
 *
 * @param iPossibleObservations number of possible observations.
 * @param iPatternLength length of each pattern (number of outcomes we are
 * selecting. According to [1], if patternLength is 0 or the same as
 * iPossibleObservations, this method will return 1
 * @return the combination amount where repetition is not allowed and order
 * is not taken into consideration.
 * @see [1]http://en.wikipedia.org/wiki/Binomial_coefficient
 */
public static BigInteger getCombinationAmountNoRepNoOrder(int iPossibleObservations, int iPatternLength) {
    if (iPatternLength == 0 || iPatternLength == iPossibleObservations) {
        return BigInteger.ONE;
    }

    BigInteger biNumOfCombinations;

    BigInteger biPossibleObservationsFactorial = factorial(iPossibleObservations);
    BigInteger biPatternLengthFactorial = factorial(iPatternLength);

    BigInteger biLastFactorial = factorial(iPossibleObservations - iPatternLength);

    biNumOfCombinations = biPossibleObservationsFactorial.divide(biPatternLengthFactorial.multiply(biLastFactorial));

    return biNumOfCombinations;
}

来自此

public static void main(String[] args) {
        System.out.print("\t" + " ");
    for (int i = 0; i <= 10; i++) {
        System.out.print("\t" + i);
    }
        System.out.print("\n");
    for (int i = 0; i <= 10; i++) {
        System.out.print("\t" + i);
        for (int j = 0; j <= 10; j++) {
            int n = i;
            int k = j;
            if (k > i) {
                System.out.print("\t0");
                continue;
            }
            BigDecimal biSterling = UtilityMath.SterlingNumber(n, k);
            System.out.print("\t" + biSterling.toPlainString());
        }
        System.out.print("\n");
    }
}

我有输出:

         0     1     2     3     4     5     6     7     8     9     10

0        1     0     0     0     0     0     0     0     0     0     0
1        0     1     0     0     0     0     0     0     0     0     0
2        0     1     1     0     0     0     0     0     0     0     0
3        0     1     3     1     0     0     0     0     0     0     0
4        0     1     7     7     1     0     0     0     0     0     0
5        0     1     5     26    11    1     0     0     0     0     0
6        0     1     31    91    66    15    1     0     0     0     0
7        0     1     63    302   351   140   22    1     0     0     0
8        0     1     127   967   1702  1050  267   28    1     0     0
9        0     1     255   3026  7771  6951  2647  462   36    1     0
10       0     1     511   9331  34106 42525 22828 5880  750   451   1