# 51Nod 1667 概率好题 - 容斥原理

若$L_{i}\leqslant x_{i} \leqslant R_{i}$，求$\sum x_{i} = 0$以及$\sum x_{i} < 0$的方案数。$(L_{i}R_{i} \geqslant 0)$（好吧。是概率）

听完题解感觉自己是个傻逼。组合数学白学了。

如果$L_{i} \neq 0$，那么取$a_{i} = x_{i} - L_{i}$。

然后容斥。

如何处理$\sum x_{i} < 0$？加一个物品$0\leqslant x_{n + 1} < \infty$。

然后做完了。

### Code

  1 /**
2  * 51nod
3  * Problem#1667
4  * Accepted
5  * Time: 187ms
6  * Memory: 2052k
7  */
8 #include <bits/stdc++.h>
9 using namespace std;
10 typedef bool boolean;
11
12 const int M = 1e9 + 7;
13 const signed int inf = (signed) (~0u >> 1);
14
15 void exgcd(int a, int b, int& x, int& y) {
16     if (!b)
17         x = 1, y = 0;
18     else {
19         exgcd(b, a % b, y, x);
20         y -= (a / b) * x;
21     }
22 }
23
24 int inv(int a, int n) {
25     int x, y;
26     exgcd(a, n, x, y);
27     return (x < 0) ? (x + n) : (x);
28 }
29
30 int add(int a, int b) {
31     a += b;
32     if (a < 0)
33         a += M;
34     if (a >= M)
35         a -= M;
36     return a;
37 }
38
39 int invs[25];
40 int n, m;
41 int K = 0;
42 int rw = 0, req = 0, rl, rall = 0;
43 int ar[20];
44
45 inline void prepare() {
46     for (int i = 1; i <= 20; i++)
47         invs[i] = inv(i, M);
48 }
49
50 inline void init() {
51     scanf("%d", &n);
52     rw = req = 0, rall = 1, K = 0;
53     for (int i = 0, l, r; i < n; i++)
54         scanf("%d%d", &l, &r), ar[i] = r - l, K -= l, rall = rall * 1ll * (ar[i] + 1) % M;
55     scanf("%d", &m);
56     for (int i = 0, l, r; i < m; i++)
57         scanf("%d%d", &l, &r), ar[n + i] = r - l, K += r, rall = rall * 1ll * (ar[n + i] + 1) % M;
58     n += m;
59 }
60
61 int C(int n, int m) {
62     int rt = 1;
63     for (int i = 0; i < m; i++)
64         rt = rt * 1ll * (n - i) % M;
65     for (int i = 1; i <= m; i++)
66         rt = rt * 1ll * invs[i] % M;
67     return rt;
68 }
69
70 int calc(int dep, int sign, int K) {
71     if (K < 0)
72         return 0;
73     if (dep == -1)
74         return sign * C(K + n - 1, n - 1);
75     return add(calc(dep - 1, -sign, K - ar[dep] - 1), calc(dep - 1, sign, K));
76 }
77
78 inline void solve() {
79     req = calc(n - 1, 1, K);
80     ar[n++] = inf;
81     rw = calc(n - 1, 1, K);
82     rl = add(rall, -rw);
83     rw = add(rw, -req);
84 //    cerr << rl << " " << req << " " << rw << endl;
85     rw = rw * 1ll * inv(rall, M) % M;
86     req = req * 1ll * inv(rall, M) % M;
87     rl = rl * 1ll * inv(rall, M) % M;
88     printf("%d %d %d\n", rl, req, rw);
89 }
90
91 int T;
92 int main() {
93     scanf("%d", &T);
94     prepare();
95     while (T--) {
96         init();
97         solve();
98     }
99     return 0;
100 }
posted @ 2018-08-04 09:54  阿波罗2003  阅读(80)  评论(0编辑  收藏