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 阅读(...) 评论(...) 编辑 收藏