题意:
已知p,q,r,s。求C(p,q) / C(r,s)。
算法:
利用组合数的计算公式
m! C(m,n) = -------- n!(m-n)!
可以得到C(p,q) = p!/(q!*(p-q)!) * = p*(p-1)*(p-2)*...*(p-q+1)/q!
C(r,s) = r!/(s!*(r-s)!) = r*(r-1)*(r-2)*...*(r-s+1)/s!
则C(p,q) / C(r,s) = p*(p-1)*(p-2)*...*(p-q+1)*s!/ [r*(r-1)*(r-2)*...*(r-s+1)*q!]
把分子分母中的每个数分解质因子,分子中的数分解的质因子对应个数+1,分母中的-1。
这实际上就是一个约分的过程。
然后计算最后结果,对于所有的质因子,如果个数>0,则乘;个数<0,则除。
===========================================================
一般处理组合数学问题的策略就是能约分的先约分,能化简的先化简,能除的先除,
不要全部乘起来再除掉
思路来源于http://www.cnblogs.com/scau20110726/archive/2013/02/04/2892324.html
这篇题解写得好赞~\(≧▽≦)/~
#include<cstdio>
#include<iostream>
#include<cstring>
#define maxn 10005
using namespace std;
int c[maxn];
void solve(int x,int f)
{
for(int i=2;x>1;i++)
{
if(x%i==0)
{
while(x>1 && !(x%i))
{
c[i]+=f;
x/=i;
}
}
}
}
int main()
{
int p,q,r,s;
while(scanf("%d%d%d%d",&p,&q,&r,&s)!=EOF)
{
memset(c,0,sizeof(c));
for(int i=p;i>=p-q+1;i--)
solve(i,1);
for(int i=s;i>=1;i--)
solve(i,1);
for(int i=r;i>=r-s+1;i--)
solve(i,-1);
for(int i=q;i>=1;i--)
solve(i,-1);
double ans = 1;
for(int i=2;i<=maxn;i++)
{
if(c[i]>0)
{
for(int j=1;j<=c[i];j++)
ans*=i;
}
else
{
c[i] = -c[i];
for(int j=1;j<=c[i];j++)
ans/=i;
}
}
printf("%.5lf\n",ans);
}
return 0;
}