【luogu P4707 重返现世】【kth min-max容斥】

题意

n n n件物品,某一时刻出现物品 i i i的概率为 p i m \frac{p_i}{m} mpi,求收集到至少 k k k件物品的期望时间。
k ≤ n ≤ 1000 , m ≤ 10000 , ∑ p i = m , n − k ≤ 10 k\le n\le 1000,m\le10000,\sum p_i=m,n-k\le 10 kn1000,m10000,pi=m,nk10

kth min-max容斥

min-max容斥: max ⁡ ( S ) = ∑ T ⊆ S ( − 1 ) ∣ T ∣ − 1 min ⁡ ( T ) \max(S)=\sum_{T\subseteq S}(-1)^{|T|-1}\min(T) max(S)=TS(1)T1min(T)
现在要推广到求 S S S得第 k k k大的元素,设大小为 m m m的集合的容斥系数为 f ( m ) f(m) f(m),那么有 k t h max ⁡ ( S ) = ∑ T ⊆ S f ( ∣ T ∣ ) min ⁡ ( T ) kth\max(S)=\sum_{T\subseteq S}f(|T|)\min(T) kthmax(S)=TSf(T)min(T)
对于第 m + 1 m+1 m+1大的元素,其对等号右边式子贡献的系数为 ∑ i = 0 m ( m i ) f ( i + 1 ) \sum_{i=0}^m\binom{m}{i}f(i+1) i=0m(im)f(i+1)
那么对于容斥系数 f ( m ) f(m) f(m)要满足 [ m = i − 1 ] = ∑ i = 0 m ( m i ) f ( i + 1 ) [m=i-1]=\sum_{i=0}^m\binom{m}{i}f(i+1) [m=i1]=i=0m(im)f(i+1)
二项式反演可得 f ( m + 1 ) = ∑ i = 0 m ( − 1 ) m − i ( m i ) [ i = k − 1 ] = ( − 1 ) m − k + 1 ( m k − 1 ) f(m+1)=\sum_{i=0}^m(-1)^{m-i}\binom{m}{i}[i=k-1]=(-1)^{m-k+1}\binom{m}{k-1} f(m+1)=i=0m(1)mi(im)[i=k1]=(1)mk+1(k1m)
所以容斥系数为 f ( m ) = ( − 1 ) m − k ( m − 1 k − 1 ) f(m)=(-1)^{m-k}\binom{m-1}{k-1} f(m)=(1)mk(k1m1)
于是有 k t h max ⁡ ( S ) = ∑ T ⊆ S ( − 1 ) ∣ T ∣ − k ( ∣ T ∣ − 1 k − 1 ) min ⁡ ( T ) kth\max(S)=\sum_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\min(T) kthmax(S)=TS(1)Tk(k1T1)min(T)

分析

通过kth min-max容斥转为求 ∑ T ⊆ S ( − 1 ) ∣ T ∣ − k ( ∣ T ∣ − 1 k − 1 ) min ⁡ ( T ) \sum_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\min(T) TS(1)Tk(k1T1)min(T)
显然 min ⁡ ( T ) = m ∑ i ∈ T p i \min(T)=\frac{m}{\sum_{i\in T}p_i} min(T)=iTpim
f i , j , k f_{i,j,k} fi,j,k表示前 i i i种物品,满足 ∑ x ∈ T p x = j \sum_{x\in T}p_x=j xTpx=j且参数为 k k k时的 ( − 1 ) ∣ T ∣ − k ( ∣ T ∣ − 1 k − 1 ) (-1)^{|T|-k}\binom{|T|-1}{k-1} (1)Tk(k1T1)之和
转移的时候考虑是否加入第 i i i种物品
若不加入,则 f i , j , k = f i − 1 , j , k f_{i,j,k}=f_{i-1,j,k} fi,j,k=fi1,j,k
若加入,可以发现 ( ∣ T ∣ − 1 k − 1 ) = ( ∣ T ∣ − 2 k − 1 ) + ( ∣ T ∣ − 2 k − 2 ) \binom{|T|-1}{k-1}=\binom{|T|-2}{k-1}+\binom{|T|-2}{k-2} (k1T1)=(k1T2)+(k2T2)
右边两项分别对应 f i − 1 , j − p i , k , f i − 1 , j − p i , k − 1 f_{i-1,j-p_i,k},f_{i-1,j-p_i,k-1} fi1,jpi,k,fi1,jpi,k1
由于系数的正负号由 k k k ∣ T ∣ |T| T来决定,现在集合大小减1,所以 f i − 1 , j − p i , k f_{i-1,j-p_i,k} fi1,jpi,k的系数为负, f i − 1 , j − p i , k − 1 f_{i-1,j-p_i,k-1} fi1,jpi,k1的系数为正。
于是 f i , j , k = f i − 1 , j − p i , k − 1 − f i − 1 , j − p i , k f_{i,j,k}=f_{i-1,j-p_i,k-1}-f_{i-1,j-p_i,k} fi,j,k=fi1,jpi,k1fi1,jpi,k
时间复杂度 O ( n m ( n − k ) ) O(nm(n-k)) O(nm(nk))

代码


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

typedef long long LL;

const int N=1005;
const int MOD=998244353;

int n,k,m,p[N],f[2][N*10][15];

int ksm(int x,int y)
{
	int ans=1;
	while (y)
	{
		if (y&1) ans=(LL)ans*x%MOD;
		x=(LL)x*x%MOD;y>>=1;
	}
	return ans;
}

int main()
{
	scanf("%d%d%d",&n,&k,&m);
	k=n-k+1;
	for (int i=1;i<=n;i++) scanf("%d",&p[i]);
	f[0][0][0]=1;
	int now=0;
	for (int i=1;i<=n;i++)
	{
		now^=1;
		for (int j=0;j<=m;j++)
			for (int l=0;l<=k;l++)
			{
				f[now][j][l]=f[now^1][j][l];
				if (l&&j>=p[i]) (f[now][j][l]+=f[now^1][j-p[i]][l-1]-f[now^1][j-p[i]][l])%=MOD,f[now][j][l]+=f[now][j][l]<0?MOD:0;
			}
	}
	int ans=0;
	for (int i=1;i<=m;i++) (ans+=(LL)f[now][i][k]*ksm(i,MOD-2)%MOD)%=MOD;
	printf("%d\n",(LL)ans*m%MOD);
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值