条件期望 以及 CF1172C2 Nauuo and Pictures (hard version) 题解

前言

再次看到这一题是在某带砖的思政课上。回忆中,第一次看到这题的时,我尚懵懂,并不会做。如今,将这题推给我的人已功成名就,而我却一无所有,不禁黯然神伤,感慨时移世异以至沧海桑田。兴许能把以前自己不会的题做出来,已然是莫大的安慰,故作文以记之。

首先考虑朴素的解法:

对于任何一幅图片,我只关心它被访问过多少次,以及当前的总和是多少,因此:
\(f[x,i,j,k]\) 表示第 \(x\) 幅照片,总共访问了 \(i\) 轮,其中除了 \(x\) 以外的 \(+1\) 访问了 \(j\) 次,除了 \(x\) 以外的 \(-1\) 访问了 \(k\) 次的概率
然后可以借助 \(i,j,k\) 的值来计算出当前状态的所有参数,从而计算转移到下一步的概率,时间复杂度 \(\mathcal O(nm^3)\)
不难发现这个做法中的很大一部分时间复杂度都是由于符号引起的,如果能把符号去掉就好了

然后不妨思考一个东西:

要是所有照片都是 \(+1\) 的就好了
如果所要照片都是 \(+1\) 的话,那么对于每个照片,我只要关心他被访问多少次即可,
因此记 \(f[x,i,j]\) 为第 \(x\) 幅照片,总共访问了 \(i\) 次,其中访问了它 \(j\) 次的概率
然后考虑一下进行第 \(i+1\) 次访问时看看有多大的概率会访问到它:
\(p=\sum_{j=0}^{i}f[x,i,j]\cdot \frac{w_0+j}{wtot+i}=\frac 1 {wtot+i}\sum_{j=0}^i f[x,i,j]\cdot(w_0+j)=\frac{\mathbb E(w)}{wtot+i}\)
这就很有意思了,你发现某一次访问某个照片的概率与具体访问过它几次无关,而与它当前的期望有关
而由于期望是线性的,某个照片当前的期望就是每一步访问它次数的期望之和,这个玩意儿可以写成一个递推式:
\(\mathbb E_{n+1}=\mathbb E_n+\frac{\mathbb E_n}{wtot+n}=\mathbb E_0 \cdot \prod_{i=0}^n (1+\frac 1 {wtot+i})\)

怎么创造所有照片的符号都相同这一个条件呢

那就是计算出来,在 \(m\) 次访问中,访问了 \(k\)\(+1\) 的概率
这个可以用一个 \(\mathcal O(m^2)\) 的 dp 来计算,然后统计答案时只需要计算条件期望的和就行了
就是 \(\mathbb E(x)=\sum \mathbb p(某种情况发生的概率)\cdot \mathbb E(这种情况必然发生的前提下的x)\)

感觉这题实质上是对于条件期望以及条件概率的考察
附代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	for(;!isdigit(ch);ch=getchar())f^=ch=='-';
	for(;isdigit(ch);ch=getchar())x=x*10+(ch^48);
	return f?x:-x;
}
const int M=3005,N=2e5+5,mo=998244353;
inline int qpow(int x,int t){
	int ret=1;
	for(;t;t>>=1,x=x*x%mo)if(t&1)ret=ret*x%mo;
	return ret;
}
inline void red(int &x){x>=mo?x-=mo:0;}
int n,m,sum[3],f[M][M],w[N],a[N],ans[N],inv[2][M],fact[2];
signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)
		a[i]=read();
	for(int i=1;i<=n;++i){
		w[i]=read();
		sum[a[i]]+=w[i];
	}
	sum[2]=sum[0]+sum[1];
	for(int i=0;i<=m;++i)for(int t=0;t<2;++t)
		inv[t][i]=qpow(sum[t]+(t?i:-i),mo-2);
	f[0][0]=1;
	for(int tot=1;tot<=m;++tot){
		for(int i=0,j=tot;i<=min(sum[0],tot);++i,--j){
			int wtot,w;
			if(i>0){
				wtot=sum[2]+j-i+1,w=sum[0]-(i-1);
				red(f[i][j]+=qpow(wtot,mo-2)*w%mo*f[i-1][j]%mo);
			}
			if(j>0){
				wtot=sum[2]+j-i-1,w=sum[1]+(j-1);
				red(f[i][j]+=qpow(wtot,mo-2)*w%mo*f[i][j-1]%mo);
			}
		}
	}
	for(int t=0;t<2;++t){
		int val=1,tag=t?1:mo-1;
		fact[t]=val*(t?f[m][0]:f[0][m]);
		for(int j=1;j<=m;++j){
			val=val*(1+tag*inv[t][j-1]%mo)%mo;
			red(fact[t]+=val*(t?f[m-j][j]:f[j][m-j])%mo);
		}
	}
	for(int i=1;i<=n;++i){
		printf("%lld\n",w[i]*fact[a[i]]%mo);
	}
	return 0;
}
posted @ 2024-11-05 14:44  chx#XCPC  阅读(4)  评论(0编辑  收藏  举报