Choose and divide UVA

来源:互联网 发布:知豆电动汽车官方电话 编辑:程序博客网 时间:2024/06/06 01:56

题目传送门

题意:给你四个数字p,q,r,s,计算C(p, q) / C(r, s)

思路:因为直接计算的话中间的结果会过大,所以不能直接计算我们可以使用唯一分解定理来把这个题目转换为阶乘这个样子就不会使中间的结果过大了。

#include <algorithm>#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <list>#include <map>#include <queue>#include <set>#include <stack>#include <string>#include <vector>#define MAXN 110000#define MAXE 5#define INF 100000000#define MOD 10001#define LL long long#define pi 3.14159using namespace std;bool prime[MAXN];LL P[MAXN];LL mi[MAXN];int cnt = 0;void is_prime() {    memset(prime, true, sizeof(prime));    for (int i = 2; i <= 10010; ++i) {        if (prime[i]) {            P[cnt++] = i;            for (int j = 2 * i; j <= 10010; j += i) {                prime[j] = false;            }        }    }}LL power(LL a, LL b) {    LL ans = 1;    while (b) {        if (b & 1) {            ans *= a;        }        b >>= 1;        a = a * a;    }    return ans;}int main() {    //std::ios::sync_with_stdio(false);    is_prime();    LL p, q, r, s;    while (~scanf("%lld%lld%lld%lld", &p, &q, &r, &s)) {        memset(mi, 0, sizeof(mi));        double sum = 1;        for (LL i = q + 1; i <= p; ++i) {            LL num = i;            for (int j = 0; j < cnt; ++j) {                LL ans = 0;                if (num == 1) {                    break;                }                while (num % P[j] == 0) {                    ans++;                    num /= P[j];                }                mi[j] += ans;            }            if (num > 1) {                sum *= num;            }        }        for (LL i = 2; i <= p - q; ++i) {            LL num = i;            for (int j = 0; j < cnt; ++j) {                LL ans = 0;                if (num == 1) {                    break;                }                while (num % P[j] == 0) {                    ans++;                    num /= P[j];                }                mi[j] -= ans;            }            if (num > 1) {                sum /= num;            }        }        for (LL i = s + 1; i <= r; ++i) {            LL num = i;            for (int j = 0; j < cnt; ++j) {                LL ans = 0;                if (num == 1) {                    break;                }                while (num % P[j] == 0) {                    ans++;                    num /= P[j];                }                mi[j] -= ans;            }            if (num > 1) {                sum /= num;            }        }        for (LL i = 2; i <= r - s; ++i) {            LL num = i;            for (int j = 0; j < cnt; ++j) {                LL ans = 0;                if (num == 1) {                    break;                }                while (num % P[j] == 0) {                    ans++;                    num /= P[j];                }                mi[j] += ans;            }            if (num > 1) {                sum *= num;            }        }        for (int i = 0; i < cnt; ++i) {            if (mi[i] > 0) {                sum *= power(P[i], mi[i]);            } else {                sum /= power(P[i], -mi[i]);            }        }        printf("%.5f\n", sum);    }    return 0;}/*10 5 14 993 45 84 59145 95 143 92995 487 996 4882000 1000 1999 9999998 4999 9996 4998 */
原创粉丝点击