/*UVa10375 - Choose and divide --考查素数因子唯一分解定理。将x!分解成素数因子,然后再进行相乘约分。考虑效率问题:组合数公式进行化简: C(m,n)=m*(m-1)*...(m-n+1)/n!来计算. */ #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<string.h> #include<algorithm> #include<cmath> using namespace std; const int maxn =10000+5; bool vis[maxn]; int prime[maxn]; //10000素数表 int pri[maxn]; int pnum; //素数个数 //生成素数表 int Euler(int n){ memset(vis, 0, sizeof(vis)); int phi = 0; for (int i = 2; i <= n; i++){ if (!vis[i]){ prime[phi++] = i;}; //i是素数 for (int j = 0; j < phi&&i*prime[j] <= n; j++){ vis[i*prime[j]] = 1; //筛去 if (i%prime[j] == 0)break; //i是合数(当前是合法的),并且这个数已经被筛过 } } return phi; //返回素数个数 } void add_integer(int n, int d){ for (int i = 0; i < pnum; i++){ while (n%prime[i] == 0){ n /= prime[i]; pri[i]+=d; } if (n == 1)break; } } //加入a*(a-1)*...(a-b+1)的素数因子 void add_factorial(int a, int b, int d){ for (int i = 0; i < b;i++) add_integer(a-i, d); } int main(){ int p, q, r, s; pnum = Euler(10000); while (~scanf("%d%d%d%d", &p, &q, &r, &s)){ memset(pri, 0, sizeof(pri)); q = min(q, p - q); s = min(s, r - s); add_factorial(p, q, 1); add_factorial(r, s, -1); if (s > q)add_factorial(s, s-q, 1); //开始这里写出一个bug搞搞死我了 else add_factorial(q, q-s, -1); double ans = 1.00; for (int i = 0; i < pnum; i++) ans *= pow(prime[i], pri[i]); printf("%.5lf ",ans); } return 0; }