Problem 53
Combinatoric selections
There are exactly ten ways of selecting three from five, 12345:
In combinatorics, we use the notation, 5C3 = 10.
In general,
nCr= n!r!(n−r)! , where r ≤ n, n! = n×(n−1)×…×3×2×1, and 0! = 1.
It is not until n = 23, that a value exceeds one-million: 23C10 = 1144066.
How many, not necessarily distinct, values of nCr, for 1 ≤ n ≤ 100, are greater than one-million?
组合数选择
从五个数12345中选择三个恰好有十种方式,分别是:
在组合数学中,我们记作:5C3 = 10。
一般来说,
nCr= n!r!(n−r)! ,其中r ≤ n,n! = n×(n−1)×…×3×2×1,且0! = 1。
直到n = 23时,才出现了超出一百万的组合数:23C10 = 1144066。
若数值相等形式不同也视为不同,对于1 ≤ n ≤ 100,有多少个组合数nCr超过一百万?
package cuppics;
import java.util.Arrays;
import junit.framework.TestCase;
public class Prj53 extends TestCase {
public void testCombinatricSelections() {
calculateCombinaticSelections(100);
}
static final int UP_LIMIT = 1000000;
static final int LIMIT_MASK = Integer.MAX_VALUE;
public static int[] calculateCombinaticSelections(int num) {
assert (num >= 1);
if (num == 1) {
return new int[] { 1, 1 };
} else if (num == 2) {
return new int[] { 1, 2, 1 };
}
int[] tmp = calculateCombinaticSelections(2);
int numOfBigThanLimit = 0;
for (int i = 3; i <= num; i++) {
int[] val = new int[i + 1];
for (int j = 0; j <= i / 2; j++) {
if (j == 0) {
val[j] = 1;
continue;
}
if (tmp[j - 1] == LIMIT_MASK || tmp[j] == LIMIT_MASK) {
val[j] = LIMIT_MASK;
numOfBigThanLimit = updateCount(numOfBigThanLimit, i, j);
break;
} else {
val[j] = tmp[j - 1] + tmp[j];
if (j == i / 2 && i % 2 == 0) {
val[j] = tmp[j - 1] * 2;
}
if (val[j] >= UP_LIMIT) {
val[j] = LIMIT_MASK;
numOfBigThanLimit = updateCount(numOfBigThanLimit, i, j);
break;
}
}
}
tmp = Arrays.copyOf(val, val.length);
}
return tmp;
}
static int updateCount(int numOfBigThanLimit, int i, int j) {
int numOf = (i + 1) / 2 - j;
numOf *= 2;
numOf = (i % 2 != 0) ? numOf : (numOf + 1);
numOfBigThanLimit += numOf;
return numOfBigThanLimit;
}
}