Cnm = n! /(m! * (n - m)!)
此时 n! 可以和 (n - m)! 约去得到 (n - m + 1) ~ n ,共 m 个数
而剩下的 1 / m! 也是 m 个数,
所以可以在代码中通过m个循环反复先乘后除缩小数据规模
long long C(int n, int m){
if(n == m || m == 0){
return 1;
}
//替换为等价值中较小的,减少循环次数
m = min(m, n - m);
long long res = 1;
for(int i = 1; i <= m; ++i){
res = res * (n - m + i) / i;
// res *= (n - m + i) / i 这种写法会先计算除法,可能损失数据造成计算错误
}
return res;
}
在这个过程中总是能除尽的,因为当除数取到 i 时,被除数已经有连续的 i 个数相乘,连续的i个数中必然有能整除 i 的。如当 i 取 3 时, 已经有连续的 3 个数如 77 78 79 ,有78可以整除,即使78 提前被 2 除了也不要紧,因为 3 是 78 的因数,可看作 3 * 26 = 78, 26 被 2 除为 14 不会引起 3 这个因数的损失。
参考: