我一直在尝试实施以下公式
公式如下
求和(从i = 1到i = K)(M选择i)* i! * StirlingNumberOfSeconfType(N,i)
用于约束
1≤N≤1000 1≤M≤1000000 1≤K≤1000
但是我没有得到大量输入的结果,任何人都能为我提供公式的有效实施吗?
答案 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
进行舍入以消除变量限制的不准确性。
注意:只有在必要时才应使用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