CF EDU 109 E - Assimilation IV
E - Assimilation IV
注意到 很小,可以算每个点被至少一个城市覆盖的概率,相加就是期望
本题中直接算点被覆盖的概率并不容易,可以算点没有被任何一个城市覆盖的概率
注意到 也很小,最大不超过
可以枚举每个点,按距离从小到大给这 个城市排序,设第 个城市与第 个点的距离为
若第 个城市覆盖不了这个点,则第 个城市要放到后 个位置
若第 个城市覆盖不了这个点,则第 个城市要放到后 个位置,但其中有一个位置已经被第 个城市占了(这就是从小到大排序的原因,保证了前一个城市要占的位置是后一个的子集) ,所以只有 个位置可以选
...
若第 个城市覆盖不了这个点,则第 个城市有 个位置可以选
求每个城市都覆盖不了这个点的概率,根据乘法原理,为 (若这个点没有位置可选了,说明这个城市一定能覆盖到这个点,所以概率为 )
#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;
}
分类:
acm / 思维
, acm / 组合数学
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话