CF EDU 109 E - Assimilation IV
阿新 • • 發佈:2022-05-18
E - Assimilation IV
注意到 \(n\) 很小,可以算每個點被至少一個城市覆蓋的概率,相加就是期望
本題中直接算點被覆蓋的概率並不容易,可以算點沒有被任何一個城市覆蓋的概率
注意到 \(d(i,j)\) 也很小,最大不超過 \(n+1\)
可以列舉每個點,按距離從小到大給這 \(n\) 個城市排序,設第 \(i\) 個城市與第 \(j\) 個點的距離為 \(dist[i]\)
若第 \(0\) 個城市覆蓋不了這個點,則第 \(0\) 個城市要放到後 \(dist[0] - 1\) 個位置
若第 \(1\) 個城市覆蓋不了這個點,則第 \(1\) 個城市要放到後 \(dist[1] - 1\)
...
若第 $ i $ 個城市覆蓋不了這個點,則第 \(i\) 個城市有 \(dist[i] - 1-i\) 個位置可以選
求每個城市都覆蓋不了這個點的概率,根據乘法原理,為 \(\prod \frac{max(0,dist[i]-1-i)}{n!}\) (若這個點沒有位置可選了,說明這個城市一定能覆蓋到這個點,所以概率為 \(0\))
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; typedef long long ll; const int N = 21, M = 5e4 + 10; const int mod = 998244353; ll fac[N], finv[N]; int d[N][M]; int n, m; ll qmi(ll a, ll b) { ll ans = 1; while(b) { if (b & 1) ans = ans * a % mod; b >>= 1; a = a * a % mod; } return ans % mod; } void presolve() { fac[0] = 1, finv[0] = 1; for (int i = 1; i < N; i++) fac[i] = fac[i-1] * i % mod; finv[N-1] = qmi(fac[N-1], mod - 2); for (int i = N - 2; i >= 1; i--) finv[i] = finv[i+1] * (i + 1) % mod; } int main() { presolve(); scanf("%d%d", &n, &m); ll ans = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", &d[i][j]); for (int j = 1; j <= m; j++) { vector<int> dist; for (int i = 1; i <= n; i++) dist.push_back(d[i][j]); sort(dist.begin(), dist.end()); ll t = 1; for (int i = 0; i < n; i++) t = t * max(0, dist[i] - 1 - i) % mod; ans = (ans + fac[n] - t) % mod; } ans = (ans + mod) % mod; ans = ans * finv[n] % mod; printf("%lld\n", ans); return 0; }