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 }