Uva--10375(数论,组合,唯一分解)
2014-09-01 20:08:45
Problem D: Choose and divide
The binomial coefficient C(m,n) is defined as
m! C(m,n) = -------- 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).
The 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 andr>=s.
The 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
Output for Sample Input
0.12587 505606.46055 1.28223 0.48996 2.00000 3.99960
思路:第二版小白书例题,参考了书里的思路,C(m,n) = m!/n!/(m-n)!,所以C(p,q) / C(r,s) = (p!*s!*(r-s)!) / (q!*r!*(p-q)!),因为p,q,r,s的大小都在10000以内,所以考虑分别对分子和分母进行唯一素数分解,从而求出答案的唯一素数分解。
1 /************************************************************************* 2 > File Name: 10375.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Mon 01 Sep 2014 07:25:01 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <iostream> 14 #include <algorithm> 15 using namespace std; 16 17 int anti_prime[10005]; 18 int e[10005]; 19 int p,q,r,s; 20 double ans; 21 vector<int> Prime; 22 23 void Erato(int n){ 24 memset(anti_prime,0,sizeof(anti_prime)); 25 int m = sqrt(n + 0.5); //limit 26 for(int i = 2; i <= m; ++i) if(!anti_prime[i]) 27 for(int j = i * i; j <= n; j += i) anti_prime[j] = 1; 28 } 29 30 void Cal_factorial(int n,int tag){ 31 for(int i = 2; i <= n; ++i){ 32 int v = i; 33 for(int j = 0; j < Prime.size(); ++j){ 34 while(v % Prime[j] == 0){ 35 v /= Prime[j]; 36 e[j] += tag; 37 } 38 if(v == 1) break; 39 } 40 } 41 } 42 43 int main(){ 44 Erato(10000); 45 for(int i = 2; i <= 10000; ++i) if(!anti_prime[i]) 46 Prime.push_back(i); 47 while(scanf("%d%d%d%d",&p,&q,&r,&s) != EOF){ 48 ans = 1.0; 49 memset(e,0,sizeof(e)); 50 Cal_factorial(p,1); 51 Cal_factorial(s,1); 52 Cal_factorial(r - s,1); 53 Cal_factorial(q,-1); 54 Cal_factorial(p - q,-1); 55 Cal_factorial(r,-1); 56 for(int i = 0; i < Prime.size(); ++i) 57 ans *= pow(1.0 * Prime[i],1.0 * e[i]); 58 printf("%.5lf\n",ans); 59 } 60 return 0; 61 } 62 63 64