这是一个非常简单的程序,它有t个测试用例,我们必须找到nCr = n!/ r!*(n-r)!. 所以它适用于较小的值,如20C2,但不适用于较大的值,如100C10。它给出32C2 = -6,100C10浮点异常。 如何使其为1< = n< = r< = 1000? 注意:我不是要求长时间加倍或不想将其更改为浮动。答案应该像100C10 = 17310309456440类似989C45 =?
#include<iostream>
using namespace std;
long long int fact(long long int num);
int main()
{
int t;
cin>>t;
long long int n[1000],r[1000],c[1000];
for(int i=0;i<t;i++)
{
cin>>n[i];
cin>>r[i];
}
for(int i=0;i<t;i++)
{
c[i]=fact(n[i])/(fact(r[i])*fact(n[i]-r[i])) ;
cout<<c[i];
}
return 0;
}
long long int fact(long long int num){
long long int k;
if(num==0)
num=1;
else
{
for(k=num-1;k>0;k--)
num=num*k;
}
return num;
}
答案 0 :(得分:1)
学习数学的时间:
nCr = fact(n)/(fact(r)*fact(n-r))
一个例子让这更容易,让我们做5C3:
5C3 = fact(5)/(fact(3)*fact(5-3))
= fact(5)/(fact(3)*fact(2))
= 5x4x3x2x1 / (3x2x1 * 2x1)
= 5x4 / 2x1
所以我们可以看到一些因素会被取消;如果完整的fact(n)
会溢出,这非常有用。
定义范围因子:
rafa(a,b) = a*(a-1)*...*(b+1)*b where a > b
= product(b..a)
然后
rafa(n,r) = fact(n)/fact(r)
-> nCr = rafa(n,r) / fact(r)
我们可以在这里停下来,我们会大大扩展n
和r
的值集,我们可以为此计算值而不会溢出。
加分
使用rafa(n,r)
和fact(r)
,我们可以看到当r
几乎与n
一样大时,问题的大部分都会取消。所以100C97 = 100x99x98 / 3x2x1 = 100x33x49。
然后考虑一个因子匹配算法(psuedo-code而不是python):
numerElems = [100,99,98]
initialDenomElems = [3,2,1]
# cancelFactors modifies numerElems values, returns un-cancelled denominator elements
def cancelFactors(numerElems, denomElems):
finalDenomElems = []
for denom in denomElems:
for factor in factorise(denom):
for idx,numer in enumerate(numerElems):
if isFactorOf(factor, numer):
numerElems[idx] = numer/factor
else
finalDenomElems.push(factor)
return finalDenomElems;
然后,您可以执行分子元素乘积的最终计算除以剩余分母元素的乘积。因为我们知道nCr总是返回一个整数结果,所以我们知道当使用cancelFactors时它总会取消所有因子。因此,该算法最大化了不溢出的n,r对的可能空间。但是,如上所述,它是O(n ^ 3 * f),其中f
是获取整数的所有因子的成本,因此它不会很快。但是,对于n和r的较大值,它可能是在不使用不同类型的情况下计算结果的唯一方法。
答案 1 :(得分:0)
您有两种选择: