• 【Luogu4707】重返现世(min-max容斥)


    【Luogu4707】重返现世(min-max容斥)

    题面

    洛谷
    求全集的(k-max)的期望

    题解

    (min-max)容斥的证明不难,只需要把所有元素排序之后考虑组合数的贡献,容斥系数先设出来后也不难解出。
    那么我们来考虑如何求解(k-max),设出容斥系数(f(|T|))

    [kmax(S)=sum_{Tsubset S}f(|T|)min(T) ]

    显然是从小到大考虑每个元素作为(min)时候的贡献,并且我们只需要其中第(k)大的贡献。
    假设(n=|S|),那么对于第(x)大的数,有:

    [[n-x+1=k]=sum_{i=0}^{n-x}{n-xchoose i}f(i+1) ]

    (x=n-x)

    [[x=k-1]=sum_{i=0}^{x}{xchoose i}f(i+1) ]

    直接套二项式反演:

    [f(x+1)=sum_{i=0}^x(-1)^{x-i}{xchoose i}[i=k-1] ]

    显然只有(i=k-1)的时候才有贡献,也就是:

    [f(x+1)=(-1)^{x-k+1}{xchoose k-1} ]

    化简后得到:

    [f(x)=(-1)^{x-k}{x-1choose k-1} ]

    好了,带回(min-max)容斥的式子,得到:

    [kmax(S)=sum_{Tsubset S}(-1)^{|T|-k}{|T|-1choose k-1}min(T) ]


    回到这题,要求的就是(kmax(All)),发现题目中给出了限制(|n-k|le 10),但是这样子符合条件的(T)依旧很多,那么我们按照(min(T))来分类,而(min(T))之和所有(T)中元素出现的概率的和相关,所以直接大力(dp)即可。

    注意一下,题目里面的(k)对应到(kmax)的时候,应该是(n-k+1),也就是第(n-k+1)大的出现时间。
    然后讲讲怎么(dp),设(f[i][j])表示当前选定的集合的(p)的和为(i),组合数那里(k=j)
    对于当前物品而言,只有两种选择:要么加入集合,要么不加入。
    如果不加入的话显然对于答案没有影响直接(f'[i][j] ightarrow f[i][j])
    否则的话加入这个元素之后会产生影响,考虑具体的转移究竟是什么。
    首先(displaystyle f[j-p][k-1]=sum(-1)^{i-(k-1)}{i-1choose k-2}Cnt[i][j-p])。其中(Cnt[i][j])表示集合大小为(i),其概率的和为(j)的方案数。
    等号右边显然就是(min-max)容斥的式子,因为要求的只是方案数,所以后面并不是(min),而是方案数。
    现在要做的就是强制把一个物品塞进去。
    塞进去的影响是什么呢?集合大小强制多了(1),并且概率的和增加了,并且我们假装(k)也改变了。
    所以塞进去后的式子是:(displaystyle sum(-1)^{i-(k-1)}{ichoose k-1}Cnt[i][j-p])
    因为组合数有简单的转移式:(displaystyle {nchoose m}={n-1choose m}+{n-1choose m-1})
    所以多出来的部分不难发现是(displaystyle -sum(-1)^{i-k}{i-1choose k-1}Cnt[i][j-p])
    也就是(-f[j-p][k])
    所以转移也就是:(f[i][j]=f'[i][j]+f'[i-p][j-1]-f'[i-p][j])

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define MAX 10100
    #define MOD 998244353
    void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,k,m,p[1010],t,ans,N,nw,pw;
    int f[2][10100][15],inv[MAX];
    int main()
    {
    	n=read();k=n-read()+1;m=read();
    	for(int i=1;i<=n;++i)p[i]=read();
    	if(!k){puts("0");return 0;}
    	for(int i=1;i<=k;++i)f[0][0][i]=MOD-1;
    	nw=1;pw=0;
    	for(int i=1,sum=0;i<=n;nw^=1,pw^=1,sum+=p[i++])
    		for(int j=0;j<=sum;++j)
    			for(int l=1;l<=k;++l)
    				if(f[pw][j][l])
    				{
    					add(f[nw][j][l],f[pw][j][l]);
    					add(f[nw][j+p[i]][l+1],f[pw][j][l]);
    					add(f[nw][j+p[i]][l],MOD-f[pw][j][l]);
    					f[pw][j][l]=0;
    				}
    	inv[0]=inv[1]=1;for(int i=2;i<=m;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
    	for(int i=1;i<=m;++i)add(ans,1ll*f[pw][i][k]*inv[i]%MOD);
    	ans=1ll*ans*m%MOD;printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    tomcat bug之部署应用的时候经常会发上startup failed due to previous errors
    maven编译项目理解
    MyReport报表引擎2.6.5.0新功能
    PHP入门-摘要表格处理问题
    EnumMap源代码阅读器
    MySQL几种方法的数据库备份
    工作日志2014-08-19
    Linux通过网卡驱动程序和版本号的信息
    JS于,子类调用父类的函数
    hdu 5007 水 弦
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10223343.html
Copyright © 2020-2023  润新知