我正在尝试解决一个非常简单的任务,即当1 <= n,k <= 50时找到nCk。我似乎找不到一种方法来输出非常大的数字(如C ++中的50)的结果。我的算法仅适用于较小的整数值。
我为nCk公式实现了阶乘函数,但是我找不到一种方法可以在1秒内解决更大的数字任务。
#include <iostream>
using namespace std;
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int i, n, k;
long long res, num, den;
res = num = den = 1;
cin >> n >> k;
if (n < k) {
cout << 0;
return 0;
}
if (n == k || k == 0) {
cout << 1;
return 0;
}
for (i = 1; i <= k; i++) {
if ((n - i + 1) % i == 0) {
res = res * ((n - i + 1) / i);
}
else {
num *= (n - i + 1);
den *= i;
}
}
cout << (res*num)/den;
return 0;
}
答案 0 :(得分:1)
此解决方案需要一些数学而不是编程(以解决溢出问题)。
您有:
n! / (k! * (n - k)!)
您可以通过扩展通用因子轻松地消除它。例如:
n = 8,k = 3
8*7*6*5*4*3*2*1 / ((3*2*1) * (5*4*3*2*1))
扩展为
8*7*6*5*4*3*2*1 / 3*2*1*5*4*3*2*1
请注意,如何通过划分规则将5*4*3*2*1
从两者中删除?然后我们得到
8*7*6 / 3*2*1
这将更容易计算。
最终,如果您不断壮大,无论如何都会遇到问题,因此您可能需要研究Boost's Multiprecision
答案 1 :(得分:0)
您当前的公式是
binom(n, k) = n! / (n - k)!k!
该公式对数学而言是确定的,但对计算而言则不是确定的。简化它:
binom(n, k) = n(n - 1)(n - 2) ... (n - k + 1) / k!
涉及较少的术语。还请注意
binom(n, k) = binom(n, n - k)
,如果k > n / 2
,则可以用作优化。
此外,如果数字太大,则需要使用GMP之类的多精度库。