题目链接
min-max进行一波扩展可以查询kth-max
min-max看这里
同样设一个容斥函数
k
t
h
−
m
a
x
{
S
}
=
∑
T
⊆
S
F
(
∣
T
∣
)
m
i
n
{
T
}
kth-max\{S\}=\sum_{T\subseteq S}F(|T|)min\{T\}
kth−max{S}=∑T⊆SF(∣T∣)min{T}
还是一样的列出每个min的出现次数
F
(
x
)
=
∑
i
=
0
x
(
x
i
)
f
(
i
+
1
)
F(x)=\sum_{i=0}^{x}{x\choose i}f(i+1)
F(x)=∑i=0x(ix)f(i+1)
显然大函数为第k大出现一次
[
x
=
=
k
−
1
]
=
∑
i
=
0
x
(
x
i
)
f
(
i
+
1
)
[x==k-1]=\sum_{i=0}^{x}{x\choose i}f(i+1)
[x==k−1]=∑i=0x(ix)f(i+1)
二项式反演得
f
(
x
+
1
)
=
∑
i
=
0
x
(
−
1
)
x
−
i
(
x
i
)
F
(
i
)
f(x+1)=\sum_{i=0}^{x}(-1)^{x-i}{x\choose i}F(i)
f(x+1)=∑i=0x(−1)x−i(ix)F(i)
f
(
x
+
1
)
=
∑
i
=
0
x
(
−
1
)
x
−
i
(
x
i
)
[
i
=
=
k
−
1
]
f(x+1)=\sum_{i=0}^{x}(-1)^{x-i}{x\choose i}[i==k-1]
f(x+1)=∑i=0x(−1)x−i(ix)[i==k−1]
f
(
x
+
1
)
=
(
−
1
)
x
−
k
+
1
(
x
k
−
1
)
f(x+1)=(-1)^{x-k+1}{x \choose k-1}
f(x+1)=(−1)x−k+1(k−1x)
f
(
x
)
=
(
−
1
)
x
−
k
(
x
−
1
k
−
1
)
f(x)=(-1)^{x-k}{x-1 \choose k-1}
f(x)=(−1)x−k(k−1x−1)
即
k
t
h
−
m
a
x
{
S
}
=
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
k
(
∣
T
∣
−
1
k
−
1
)
m
i
n
{
T
}
kth-max\{S\}=\sum_{T\subseteq S}(-1)^{|T|-k}{|T|-1 \choose k-1}min\{T\}
kth−max{S}=∑T⊆S(−1)∣T∣−k(k−1∣T∣−1)min{T}
这样子就可以把kth-max转化成min
很显然每个min的期望贡献都是集合概率和的倒数,我们可以放一下最后求
先求一下
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
k
(
∣
T
∣
−
1
k
−
1
)
\sum_{T\subseteq S}(-1)^{|T|-k}{|T|-1 \choose k-1}
∑T⊆S(−1)∣T∣−k(k−1∣T∣−1)
考虑DP转移
假设
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]表示前
i
i
i种中选出一个集合使其概率为
j
j
j的
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
k
(
∣
T
∣
−
1
k
−
1
)
\sum_{T\subseteq S}(-1)^{|T|-k}{|T|-1 \choose k-1}
∑T⊆S(−1)∣T∣−k(k−1∣T∣−1)
显然对于第i个有两种情况,选或者不选
不选的话很简单
d
p
[
i
]
[
j
]
[
k
]
=
d
p
[
i
−
1
]
[
j
]
[
k
]
dp[i][j][k]=dp[i-1][j][k]
dp[i][j][k]=dp[i−1][j][k]
选的话有点小问题,可以发现虽然
i
i
i从
i
−
1
i-1
i−1转移,
j
j
j从
j
−
p
i
j-p_i
j−pi转移很套路,但是新加进来一个数以后集合大小增加了1,就需要稍微推一下了
每次大小增加1,正负性就会发生改变
根据组合数的递推式,
(
∣
T
∣
−
1
k
−
1
)
=
(
∣
T
∣
−
2
k
−
1
)
+
(
∣
T
∣
−
2
k
−
2
)
{|T|-1 \choose k-1}={|T|-2 \choose k-1}+{|T|-2 \choose k-2}
(k−1∣T∣−1)=(k−1∣T∣−2)+(k−2∣T∣−2)
然后正负性与
∣
T
∣
,
k
|T|,k
∣T∣,k都有关,所以等式后第一个的贡献是负的,而第二个的贡献是正的
也就是
d
p
[
i
]
[
j
]
[
k
]
=
d
p
[
i
−
1
]
[
j
−
p
i
]
[
k
−
1
]
−
d
p
[
i
−
1
]
[
j
−
p
i
]
[
k
]
dp[i][j][k]=dp[i-1][j-p_i][k-1]-dp[i-1][j-p_i][k]
dp[i][j][k]=dp[i−1][j−pi][k−1]−dp[i−1][j−pi][k]
边界条件的话
d
p
[
i
]
[
0
]
[
0
]
=
1
dp[i][0][0]=1
dp[i][0][0]=1,这个并不是唯一的,但是按照这样子赋有实际意义:考虑上面那个容斥函数,我们只有一个空集,所以这里的
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
k
(
∣
T
∣
−
1
k
−
1
)
=
1
\sum_{T\subseteq S}(-1)^{|T|-k}{|T|-1 \choose k-1}=1
∑T⊆S(−1)∣T∣−k(k−1∣T∣−1)=1
然后只是从i-1和i转移过来,所以开个滚动数组优化一下空间
统计答案的时候乘上概率的逆元就是答案了
代码如下:
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
long long kasumi(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
long long dp[2][20000][12];
int p[2000];
int n,m,k,pre=0,now=1;
int main()
{
scanf("%d%d%d",&n,&k,&m);
k=n-k+1;
now=1;
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
dp[0][0][0]=1;
now=1,pre=0;
for(int i=1;i<=n;i++)
{
dp[now][0][0]=1;
for(int j=0;j<=m;j++)
{
for(int h=0;h<=k;h++)
{
dp[now][j][h]=dp[pre][j][h];
if(j>=p[i]&&h!=0)
{
dp[now][j][h]=(dp[now][j][h]+(dp[pre][j-p[i]][h-1]-dp[pre][j-p[i]][h]+mod)%mod)%mod;
}
}
}
now^=1,pre^=1;
}
long long ans=0;
for(int i=1;i<=m;i++)
{
ans+=dp[pre][i][k]*kasumi(i,mod-2)%mod;
ans%=mod;
}
printf("%lld\n",ans*m%mod);
}