|

[题解] CF1854C Expected Destruction

CF1854C Expected Destruction *2500

tag:概率期望

题目大意

给出一个包含 \(n\) 个元素 \(s_{1\cdots n}\) 的集合 \(S\),每次操作会等概率随机一个 \(S\) 中的数字进行如下操作:

  • 设选中的数字为 \(x\),将 \(x\)\(S\) 中删去
  • \(x+1\le m\)\(x+1\) 不在 \(S\) 中,则将 \(x+1\) 加入到 \(S\)

问将 \(S\) 变成空集的期望操作次数 \(\bmod 10^9+7\)

\(1\le n\le m\le 500\)\(s_i\) 单增,\(\texttt{1s,256M}\)

思路

  1. 由期望的线性性,可以尝试将每个元素分开来看,求出每个元素撞上 \(x+1\) 所需要的期望操作次数
  2. 但问题是可能 \(x\) 再撞上 \(x+1\) 之前,\(x+1\) 已经撞上另一个更大的数字消失了,此时我们认为并不是 \(x+1\) 消失,而是那个更大的数字消失,除非移动到了 \(m+1\),这样 \(x+1\) 就永远不会消失了
  3. 因此问题变成了只考虑 \(x\)\(x+1\) 之间的关系,可以设 dp[i][j] 表示前一个在 \(i\),后一个在 \(j\) 的期望移动次数,那么边界条件为 dp[i][i]=0 以及 dp[i][m+1]=m+1-i,转移分两种情况,\(i,j\) 被选中的概率均为 \(\frac{1}{2}\),那么可以得到转移 dp[i][j]=((dp[i+1][j]+1)+dp[i][j+1])/2 就可以求出所有的 dp 值了
  4. 最终答案即为所有 dp[s[i]][s[i+1]] 的和(最后添加一个 \(s_{n+1}=m+1\)
  5. 时空复杂度 \(O(m^2)\)
#include<bits/stdc++.h>
using namespace std;
const int N=505,mod=1e9+7,Inv2=(mod+1)/2;
int n,m,ans,dp[N][N],a[N];
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1; i<=m+1; i++) dp[i][m+1]=m+1-i,dp[i][i]=0;
	for (int i=m; i>=1; i--)
		for (int j=m; j>i; j--)
			dp[i][j]=1ll*(dp[i+1][j]+1+dp[i][j+1])*Inv2%mod;
	for (int i=1; i<=n; i++) scanf("%d",&a[i]); a[n+1]=m+1;
	for (int i=1; i<=n; i++) ans=(ans+dp[a[i]][a[i+1]])%mod;
	printf("%d\n",ans);
}
posted @ 2025-07-01 11:10  wishapig  阅读(8)  评论(0)    收藏  举报