并
题目大意
给定$n$个矩形,对于每个$k\in [1,n]$,求解选$k$个不同矩形形成的面积并的期望。
解题思路
通过离散化+二位前缀和,求出被覆盖$i$次的面积记作$res[i]$。对于所有$k$,考虑求出被覆盖$i$次的面积的概率,总的情况是$C_n^k$,直接求出选到覆盖$i$次的这块面积的情况数量需要平方的复杂度,考虑正难则反(容斥),没选到这块面积的情况数就是我选的$k$次都是没有覆盖这块面积的矩形,即$C_{n-i}^k$,所以选到这块面积的情况数量就是$C_n^k-C_{n-i}^k$,概率就是$\frac{C_n^k-C_{n-i}^k}{C_n^j}$,期望即$\frac{C_n^k-C_{n-i}^k}{C_n^j}\times res[i]$。
时间复杂度$O(n^2)$
参考代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| #include <bits/stdc++.h> #define maxn 4010 #define int long long using namespace std; const double eps = 1e-8; const int mod = 998244353; int s[maxn][maxn], C[maxn][maxn], wk[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; int x1_[maxn], y1_[maxn], x2_[maxn], y2_[maxn]; int res[maxn]; bool vis[maxn][maxn]; int nx[maxn], ny[maxn];
int qmi(int a, int b, int m) { int res = 1; a %= m; while(b) { if(b & 1) res = res * a % m; a = a * a % m; b >>= 1; } return res; }
void solve() { map<int, int>xs, ys; set<int> numx, numy; int n; cin >> n; for (int i = 1; i <= n; ++i) { cin >> x1_[i] >> y1_[i] >> x2_[i] >> y2_[i]; numx.insert(x1_[i]); numy.insert(y1_[i]); numx.insert(x2_[i]); numy.insert(y2_[i]); } int curx = 0, cury = 0;
for (auto u : numx) { xs[u] = ++curx; nx[curx] = u; } for (auto u : numy) { ys[u] = ++cury; ny[cury] = u; } for (int i = 1; i <= n; ++i) { s[xs[x1_[i]]][ys[y1_[i]]]++; s[xs[x2_[i]]][ys[y1_[i]]]--; s[xs[x1_[i]]][ys[y2_[i]]]--; s[xs[x2_[i]]][ys[y2_[i]]]++; } for (int i = 1; i <= curx; ++i) { for (int j = 1; j <= cury; ++j) { s[i][j] = s[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1]; } }
for(int i = 1; i < curx; i++) { for(int j = 1; j < cury; j++) { int dx = nx[i + 1] - nx[i]; int dy = ny[j + 1] - ny[j]; res[s[i][j]] = (res[s[i][j]] + dx * dy % mod) % mod; } } for(int i = 1; i <= n; i++) { int ans = 0; int tt = qmi(C[n][i], mod - 2, mod); for(int j = 1; j <= n; j++) { ans = (ans + res[j] * (C[n][i] - C[n - j][i] + mod) % mod * tt) % mod; } cout << ans << '\n'; }
}
signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); for (int i = 0; i <= 2000; ++i) { for (int j = 0; j <= i; ++j) { if(j == 0 || j == i) C[i][j] = 1; else C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; } } int t = 1; while (t--) { solve(); } return 0; }
|