Educational Codeforces Round 109 (Rated for Div. 2) E. Assimilation IV(期望的线性性质)
题意是有 n 个城市和 m 个点,已知每个城市到每个点的距离为,每秒进行一次操作,每次随机选一个没选过的城市建一个碑,其影响的范围每秒加一,求 n 秒后被影响的点数的期望。
朴素的想法是枚举建碑的方案,然后暴力判断每种方案能覆盖多少点,但n最大为20,枚举阶乘显然会t。这时就要用到概率题目的常见思想:转变所求目标。既然方案不好考虑,那么就考虑点。我们要求的期望实际上是,其中是指示函数,由期望的线性性质,,即这个点被覆盖的概率。因为每种建碑方案会将点与点之间联系起来,因此使用线性性质可以将问题转化为单独求每个点的概率。因为每个点可能会被重复覆盖,所以将每个点被覆盖的概率转化为1-不被覆盖的概率。设当前考虑的点为i,将n个碑到i的距离从小到大排序。设最近的那个碑到当前点的距离为d[0],那么需要把它放到后d[0]-1个位置中的某个位置(这样才能保证这个碑永远不会覆盖到当前点);次近的碑需要放到后d[1]-1-1个位置(为什么d[1]-1以后还要再减1?因为按照距离排序后,前一个碑肯定已经在后d[1]-1个位置中占据一个了)...由乘法原理,可得当前点不被覆盖的概率为,和0取max是因为如果减为负数说明当前点无论如何都会被覆盖。就是当前点被覆盖的概率。对所有的点求概率,相加即为答案。
#include <bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
int n, m;
int d[25][50005];
int fpow(int a, int b) {
int ans = 1;
for(; b; b >>= 1) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
}
return ans;
}
void solve() {
cin >> n >> m;
int inv = 1;
for(int i = 1; i <= n; i++) {
inv = inv * fpow(i, mod - 2) % mod;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin >> d[i][j];
}
}
int ans = 0;
for(int i = 1; i <= m; i++) {
vector<int> v;
for(int j = 1; j <= n; j++) {
v.push_back(d[j][i]);
}
sort(v.begin(), v.end());
int tmp = 1;
for(int j = 0; j < v.size(); j++) {
tmp = tmp * max(0ll, v[j] - 1 - j) % mod;
}
tmp = tmp * inv % mod;
tmp = (1 - tmp + mod) % mod;
ans = (ans + tmp) % mod;
}
cout << ans << endl;
}
signed main() {
int T = 1;
while(T--) {
solve();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2021-11-11 2020CCPC长春 F. Strange Memory(树上启发式合并)
2021-11-11 2020CCPC长春 D. Meaningless Sequence(打表/数位DP)
2020-11-11 AcWing 1224. 交换瓶子(交换最少次数使得数列有序)
2020-11-11 AcWing 1220. 生命之树(树形DP)