c ++中较大值的数学计算

时间:2014-11-21 10:50:27

标签: c++ algorithm math combinators binomial-coefficients

这是一个非常简单的程序,它有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;
}

2 个答案:

答案 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)

我们可以在这里停下来,我们会大大扩展nr的值集,我们可以为此计算值而不会溢出。

加分

使用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)

您有两种选择:

  1. 使用多精度库,例如Boost提供的库:
  2. http://www.boost.org/doc/libs/1_53_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/egs/factorials.html

    1. 尽可能尝试简化表达。只要您的值仍然很小,这将有效。看看分子和分母?你能简化一下吗?当您改变N和R时,值如何变化?有些情况下,这些部分结果较小。尽量使用它。