LG4707 重返现世[min-max 容斥][概率期望]
首先要有一些 kthmin-max 容斥的基本知识,不讲了。
求第 k 小,相应的转化成第 n-k+1 大。
\begin{aligned}E(kthmax(S)) &= \sum_{T \subseteq S} (-1)^{|T|-k} {|T|-1 \choose k-1}E(min(T)) \\& = m\sum_{T \subseteq S} (-1)^{|T|-k} {|T|-1 \choose k-1} {1 \over \sum_{i \in T}a_i}\end{aligned}
注意到 m 在一个可接受的范围。
一个比较显然的想法是记 f_{i,j,d} 表示前 i 个,和为 j,已选 d 个的方案数。
那这是一个经典背包,O(n^2m),可以获得 70 分。
接下来是这题 dp 状态比较神仙的部分。
设 f_{i,j,k} 表示前 i 个,\sum_{T \subseteq S} (-1)^{|T|-k}{|T|-1 \choose k-1} [\sum_{i \in T} a-i == j] 的值。注意此处 k 的定义与题面不同。
对于 i 这个数,要么选,要么不选。如果不选,直接继承状态。
如果选:
\begin{aligned}f_{i,j,k} +&= \sum_{T \subseteq S,i \in T} (-1)^{|T|-k} {|T|-1 \choose k-1} [\sum_{x \in T} a_x = j]\\& = \sum_{T \subseteq S} (-1)^{|T|-k+1} {|T|\choose k-1} [\sum_{x \in T} a_x = j-a_i]\\ & = \sum_{T \subseteq S} (-1)^{|T|-k+1}[{|T|-1 \choose k-1}+ {|T|-1 \choose k-2}][\sum_{x \in T} a_x = j-a_i]\\& = (\sum_{T \subseteq S} (-1)^{|T|-k+1} {|T|-1\choose k-1} + \sum_{T \subseteq S}(-1)^{|T|-k+1}{|T|-1\choose k-2})[\sum_{x \in T} a_x = j-a_i]\\& = f_{i-1,j-a_i,k-1}-f_{i-1,j-a_i,k}\end{aligned}
边界条件是 f_{0,0,0} = 1。
非常的牛逼。
#include<bits/stdc++.h>
#define rep(i,a,b) for (register int i=(a);i<=(b);i++)
#define drep(i,a,b) for (register int i=(a);i>=(b);i--)
typedef long long ll;
using namespace std;
inline ll read()
{
ll sum=0,f=0;char c=getchar();
while (!isdigit(c)) f|=(c=='-'),c=getchar();
while (isdigit(c)) sum=(sum<<1)+(sum<<3)+(c^48),c=getchar();
return f?-sum:sum;
}
const int mod=998244353;
inline int qmo(int x){return x+((x>>31)&mod);}
inline int add(int x,int y){return qmo(x+y-mod);}
inline int sub(int x,int y){return qmo(x-y);}
inline void inc(int &x,int y){x=add(x,y);}
inline void dec(int &x,int y){x=sub(x,y);}
inline int quick_pow(int x,int k){int res=1;for (;k;k>>=1,x=1ll*x*x%mod) if (k&1) res=1ll*res*x%mod;return res;}
const int N=1010;
const int M=10010;
const int K=15;
int fac[M],_fac[M],pw[M];
inline void init(int size)
{
*fac=*_fac=*pw=1;
rep(i,1,size) pw[i]=mod-pw[i-1];
rep(i,1,size) fac[i]=1ll*fac[i-1]*i%mod;
_fac[size]=quick_pow(fac[size],mod-2);
drep(i,size-1,1) _fac[i]=1ll*_fac[i+1]*(i+1)%mod;
}
inline int C(int n,int m){return n>=m&&m>=0?1ll*fac[n]*_fac[m]%mod*_fac[n-m]%mod:0;}
inline int inv(int x){return 1ll*fac[x-1]*_fac[x]%mod;}
int n,k,m,g[2][M][K],f[N],a[N],ans;
int main()
{
n=read(),k=n-read()+1,m=read(); rep(i,1,n) a[i]=read();
g[0][0][0]=1; init(M-10);
rep(i,1,n)
{
int t=i&1; memset(g[t],0,sizeof(g[t]));
rep(j,0,m) rep(d,0,k) inc(g[t][j][d],g[t^1][j][d]);
rep(j,a[i],m) rep(d,1,k)
{
inc(g[t][j][d],sub(g[t^1][j-a[i]][d-1],g[t^1][j-a[i]][d]));
}
}
rep(j,0,m) inc(ans,1ll*m*inv(j)%mod*g[n&1][j][k]%mod);
cout<<ans<<endl;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步