UVA 10375

The binomial coefficient C(m,n) is defined as C(m,n)=
m!
--------
n!(m-n)!

Given four natural numbers p, q, r, and s, compute the the result of dividing C(p,q) by C(r,s).

Input

Input consists of a sequence of lines. Each line contains four non-negative integer numbers giving values for p, q, r, and s, respectively, separated by a single space. All the numbers will be smaller than 10,000 with p>=q and r>=s.

Output

For each line of input, print a single line containing a real number with 5 digits of precision in the fraction, giving the number as described above. You may assume the result is not greater than 100,000,000.

Sample Input

10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998

Sample Output

0.12587
505606.46055
1.28223
0.48996
2.00000
3.99960

题目大意:
这道题是两个组合数相除,求C(p,q)/C(r,s)。

解题思路:
因为范围有1e4,所以常规做数据范围是装不下的,我们要用唯一分解定理把这个式子分解成多个质数然后不断约分即可。
唯一分解定理:任何一个大于1的自然数 N,N一定可以唯一分解成有限个质数的乘积。(百度百科)
我们先把这个范围内的素数筛出来(我用的是埃氏筛法),用一个数组去存这些数的状态,然后开始对分子分母的每一个数进行分解,看看他对最后的答案贡献了几个质数,把这个式子整理一下,就可以得到分子分母,因为要约分,所以对于分子,每一个出现的质数的数量都+1,分母每个出现的质数的数量都-1,最后就可以得到这个质数最终的个数了。AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
using LL = long long;
const int _max=1e4+50;
LL a[_max],num[_max],cnt=0;
bool prime[_max];
void isprime()
{
	memset(prime,false,sizeof prime);
	for(int i=2;i<=_max;i++)
	  if(!prime[i])
	  {
		  num[cnt++]=i;//num用来存放第cnt个质数是多少
		  for(int j=i*2;j<=_max;j+=i)
		    prime[j]=true;
	  }
}
void solve(int n,int d)//对该数进行分解质因子
{
	for(int i=0;i<cnt;i++)
	{
		while(n%num[i]==0)
		{
			n/=num[i];
			a[i]+=d;//第 i 个质数要+1或-1
		}
		if(n==1)//不加会TLE,我们要在n==1的时候提前退出循环,不然遍历的次数太多
		 return;
	}
}
int main()
{
	double ans;
	int p,q,r,s;
	isprime();
	while(cin>>p>>q>>r>>s)
	{
		ans=1;
		memset(a,0,sizeof a);
		for(int i=1;i<=p;i++) solve(i,1);//分子+1
		for(int i=1;i<=r-s;i++) solve(i,1);
		for(int i=1;i<=s;i++) solve(i,1);

		for(int i=1;i<=p-q;i++) solve(i,-1);//分母-1
		for(int i=1;i<=q;i++) solve(i,-1);
		for(int i=1;i<=r;i++) solve(i,-1);
		for(int i=0;i<cnt;i++)
		  if(num[i])
		    ans*=pow(num[i],a[i]);
		printf("%.5lf
",ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Hayasaka/p/14294276.html