在用计算机计算排列组合时,由于阶乘极易导致溢出,在这里我们使用略微耗时的算法替代直接阶乘
相关数学等式
int getGCD(int first,int second) //辗转相除,求最大公约数
{
return !second?first:getGCD(second,first%second);
}
int getResult(int m,int n)
{
int arraySize,minDividend,maxDivision,ret=1;
if(m-n>n){ //根据Cm,n = Cm,m-n(m为下标,n为上标)性质,尽可能减少计算次数
arraySize = n;
minDividend = m-n+1;
maxDivision = n;
}else{
arraySize = m-n;
minDividend = n+1;
maxDivision = m-n;
}
int *dividendArray = (int *)malloc(sizeof(int)*arraySize);//分子
int *divisionArray = (int *)malloc(sizeof(int)*arraySize);//分母
if(!dividendArray || !divisionArray){
free(dividendArray);
free(divisionArray);
exit(1);
}
for(int iLoad=m;iLoad>=minDividend;iLoad--){ //保存分子
dividendArray[m-iLoad] = iLoad;
}
for(int iLoad=maxDivision;iLoad>=1;iLoad--){ //保存分母
divisionArray[maxDivision-iLoad] = iLoad;
}
for(int iUnload=0;iUnload<arraySize;iUnload++){//开始约分
for(int iTry=0;iTry<arraySize;iTry++){
if(dividendArray[iTry]>1){ //如果为1,则直接跳过
int GCD = getGCD(dividendArray[iTry],divisionArray[iUnload]);//判断是否能整除
dividendArray[iTry] /= GCD;
divisionArray[iUnload] /= GCD;
if(divisionArray[iUnload]==1){ //一项约分完毕,返回
break;
}
}
}
}
for(int iRet=m;iRet>=minDividend;iRet--) //将约分后分子整合
{
ret *= dividendArray[m-iRet];
}
return ret;
}