当前位置: 首页 > 工具软件 > Ender > 使用案例 >

Ender的模拟赛D2T1 wait【min-max反演】

詹弘毅
2023-12-01

题目描述

有一n*m的棋盘,每次随机染黑一个位置(可能染到已经黑了的),当某一行或者一列全为黑色时停止,求期望染色次数(mod 998244353)
对于100%的数据n,m<=1000

题目分析

考完听说是模板题
显然这个“当xxx时停止”非常不好处理,我们不知道它到底有没有停止,方案也很难统计。
不考虑停止,一直染,用 a 1 , a 2 … a n a_1,a_2\dots a_n a1,a2an表示 a i a_i ai行全黑时的次数,用 b j b_j bj表示 b j b_j bj列全黑时的次数。
我们想知道 E ( min ⁡ { a 1 , a 2 … a n , b 1 , b 2 … b m } ) E\left(\min\{a_1,a_2\dots a_n,b_1,b_2\dots b_m\}\right) E(min{a1,a2an,b1,b2bm})
上minmax反演:
min ⁡ ( S ) = ∑ T ⊆ S , T ≠ ∅ ( − 1 ) ∣ T ∣ − 1 max ⁡ ( T ) \min(S)=\sum_{T\subseteq S,T\ne\empty}(-1)^{|T|-1}\max(T) min(S)=TS,T̸=(1)T1max(T)
证明:设 s 1 ≤ s 2 ⋯ ≤ s N s_1\le s_2\dots\le s_N s1s2sN,考虑 s i s_i si在右式的贡献: s i s_i si作为max,剩下的数在 s 1 s_1 s1 s i − 1 s_{i-1} si1随便选。当 i &gt; 1 i&gt;1 i>1时,集合数为 2 i − 1 2^{i-1} 2i1,集合奇偶各占一半,相互抵消;当 i = 1 i=1 i=1时,集合数为1,贡献为 s 1 s_1 s1,得证。
在外面套上一个期望,上式仍然成立。
选出 i i i行, j j j列, a , b a,b a,b的max就是把这 i i i j j j列全部染黑的次数,总个数是 k = i m + j n − i j k=im+jn-ij k=im+jnij,染到第一个的概率是 k n m \frac k{nm} nmk,期望次数就是 n m k \frac {nm}k knm,染第二个的期望次数就是 n m k − 1 \frac {nm}{k-1} k1nm。所以
E ( min ⁡ ( a . . , b . . ) ) = ∑ i = 0 n ∑ j = 0 m [ i ∣ ∣ j ] ( n i ) ( m j ) n m ( 1 + 1 2 + . . . + 1 i m + j n − i j ) E(\min(a..,b..))=\sum_{i=0}^n\sum_{j=0}^m[i||j]{n\choose i}{m\choose j}nm(1+\frac 12+...+\frac 1{im+jn-ij}) E(min(a..,b..))=i=0nj=0m[ij](in)(jm)nm(1+21+...+im+jnij1)

附上minmax反演的学习

Code:

#include<bits/stdc++.h>
#define maxn 1005
using namespace std;
const int mod = 998244353;
int n,m,ans,c[maxn][maxn],inv[maxn*maxn],s[maxn*maxn];
int main()
{
	freopen("wait.in","r",stdin);
	freopen("wait.out","w",stdout);
	scanf("%d%d",&n,&m);
	c[0][0]=1;
	for(int i=1;i<=max(n,m);i++){
		c[i][0]=c[i][i]=1;
		for(int j=1;j<i;j++) 
			c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
	}
	inv[0]=inv[1]=1,s[1]=n*m;
	for(int i=2;i<=n*m;i++) 
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod,
		s[i]=(s[i-1]+1ll*n*m*inv[i])%mod;
	for(int i=0;i<=n;i++)
		for(int j=0;j<=m;j++) if(i||j)
			ans=(ans+1ll*((i+j)&1?1:-1)*c[n][i]*c[m][j]%mod*s[i*m+j*n-i*j])%mod;
	printf("%d\n",(ans+mod)%mod);
}
 类似资料: