关于
m
i
n
−
m
a
x
min-max
min−max容斥,我们希望构造一个系数使得
m
a
x
(
s
)
=
∑
T
⊆
S
f
∣
T
∣
m
i
n
(
T
)
max(s)=\sum_{T\subseteq S}f_{|T|}min(T)
max(s)=∑T⊆Sf∣T∣min(T)
考虑
k
+
1
k+1
k+1 大的贡献
m
a
x
(
s
)
=
∑
i
=
0
k
(
k
i
)
f
i
+
1
=
[
k
=
0
]
max(s)=\sum_{i=0}^k\binom{k}{i}f_{i+1}=[k=0]
max(s)=∑i=0k(ik)fi+1=[k=0]
反演得
f
k
+
1
=
∑
i
=
0
k
(
−
1
)
k
−
i
[
i
=
0
]
(
k
i
)
=
(
−
1
)
k
f_{k+1}=\sum_{i=0}^k(-1)^{k-i}[i=0]\binom{k}{i}=(-1)^k
fk+1=∑i=0k(−1)k−i[i=0](ik)=(−1)k
所以
f
∣
T
∣
=
(
−
1
)
∣
T
∣
−
1
f_{|T|}=(-1)^{|T|-1}
f∣T∣=(−1)∣T∣−1
关于
k
t
h
−
m
i
n
−
m
a
x
kth-min-max
kth−min−max 容斥,同上考虑
k
+
1
k + 1
k+1 大的贡献
k
t
h
−
m
a
x
(
s
)
=
∑
i
=
0
k
(
k
i
)
f
i
+
1
=
[
k
=
r
k
−
1
]
kth-max(s)=\sum_{i=0}^k\binom{k}{i}f_{i+1}=[k=rk-1]
kth−max(s)=∑i=0k(ik)fi+1=[k=rk−1]
反演得
f
k
+
1
=
∑
i
=
0
k
(
−
1
)
k
−
i
(
k
i
)
[
i
=
r
k
−
1
]
=
(
−
1
)
k
−
r
k
+
1
(
k
r
k
−
1
)
f_{k+1}=\sum_{i=0}^k(-1)^{k-i}\binom{k}{i}[i=rk-1]=(-1)^{k-rk+1}\binom{k}{rk-1}
fk+1=∑i=0k(−1)k−i(ik)[i=rk−1]=(−1)k−rk+1(rk−1k)
所以
f
∣
T
∣
=
(
−
1
)
∣
T
∣
−
r
k
(
∣
T
∣
−
1
r
k
−
1
)
f_{|T|}=(-1)^{|T|-rk}\binom{|T|-1}{rk-1}
f∣T∣=(−1)∣T∣−rk(rk−1∣T∣−1)
HDU4624:Endless Spin
题意:给一个长为m 的白球序列,每次随机一个区间,把区间内的球全部染为黑色,求把所有球染黑的期望步数
考虑到
a
n
s
=
m
a
x
(
p
i
)
ans=max(p_i)
ans=max(pi)不好求,转换为求
m
i
n
(
p
i
)
min(p_i)
min(pi) 然后反演
一个集合的最小期望就是这个集合第一个被染到的点的期望时间
发现为 总个数/能覆盖一个点的区间个数
但我们不能枚举集合,考虑到能覆盖到一个点的区间个数很少,想到了
d
p
dp
dp
f
i
,
j
,
0
/
1
f_{i,j,0/1}
fi,j,0/1 为当前选到了第 i 个位置,不能覆盖一个点的个数是 j,最后一维是容斥的系数
f
i
,
j
+
(
i
−
p
−
1
2
)
+
=
f
p
,
j
f_{i,j+\binom{i-p-1}{2}}+=f_{p,j}
fi,j+(2i−p−1)+=fp,j
#include<bits/stdc++.h>
#define N 55
typedef long long ll;
using namespace std;
int T, n; ll f[N][N*N][2];
int P(int x){ return x * (x + 1) / 2;}
int main(){
scanf("%d", &T);
while(T--){
scanf("%d", &n);
memset(f, 0, sizeof(f));
f[0][0][0] = 1;
for(int i = 1; i <= n; i++)
for(int j = 0; j < i; j++)
for(int k = P(i - j - 1); k <= P(i); k++)
for(int l = 0; l < 2; l++)
f[i][k][l] += f[j][k - P(i - j - 1)][l ^ 1];
double ans = 0; int tot = P(n);
for(int i = 1; i <= n; i++){
for(int j = 0; j <= P(i); j++){
for(int l = 0; l < 2; l++){
if(l & 1) {if(f[i][j][l]) ans += 1.0 * f[i][j][l] * tot / (tot - j - P(n - i));}
else { if(f[i][j][l])ans -= 1.0 * f[i][j][l] * tot / (tot - j - P(n - i));}
}
}
} printf("%.15lf\n", ans);
} return 0;
}
重返现世
求
k
t
h
−
m
i
n
(
p
i
)
kth-min(p_i)
kth−min(pi)
考虑到
n
−
k
n-k
n−k很小,于是把
k
k
k换成
n
−
k
+
1
n-k+1
n−k+1,变成求
k
t
h
−
m
a
x
(
p
i
)
kth-max(p_i)
kth−max(pi)
而
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}\binom{|T|-1}{k-1}min(T)
kth−max(S)=∑T⊆S(−1)∣T∣−k(k−1∣T∣−1)min(T)
而
m
i
n
(
S
)
=
m
∑
i
∈
S
p
i
min(S)=\frac{m}{\sum_{i\in S}p_i}
min(S)=∑i∈Spim
同样又不能枚举集合,而
∑
p
i
\sum p_i
∑pi 的个数非常少
于是令
f
i
,
j
,
k
f_{i,j,k}
fi,j,k 表示到第 i 个,当前
p
i
p_i
pi 的和,现在求的是第 k 大的
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
k
(
∣
T
∣
−
1
k
−
1
)
m
i
n
(
T
)
\sum_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}min(T)
∑T⊆S(−1)∣T∣−k(k−1∣T∣−1)min(T)的值
如果不选
f
i
,
j
,
k
=
f
i
−
1
,
j
,
k
f_{i,j,k}=f_{i-1,j,k}
fi,j,k=fi−1,j,k
如果选,所有的
∣
T
∣
|T|
∣T∣ 要变成
∣
T
∣
+
1
|T|+1
∣T∣+1
也就是
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
k
(
∣
T
∣
−
1
k
−
1
)
m
i
n
(
T
)
\sum_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}min(T)
∑T⊆S(−1)∣T∣−k(k−1∣T∣−1)min(T)变成
∑
T
⊆
S
(
−
1
)
∣
T
+
1
∣
−
k
(
∣
T
∣
k
−
1
)
m
i
n
(
T
)
\sum_{T\subseteq S}(-1)^{|T+1|-k}\binom{|T|}{k-1}min(T)
∑T⊆S(−1)∣T+1∣−k(k−1∣T∣)min(T)
而
∑
T
⊆
S
(
−
1
)
∣
T
+
1
∣
−
k
(
∣
T
∣
k
−
1
)
m
i
n
(
T
)
=
∑
T
⊆
S
(
−
1
)
∣
T
+
1
∣
−
k
(
(
∣
T
∣
−
1
k
−
1
)
+
(
∣
T
−
1
∣
k
−
2
)
)
m
i
n
(
T
)
\sum_{T\subseteq S}(-1)^{|T+1|-k}\binom{|T|}{k-1}min(T)=\sum_{T\subseteq S}(-1)^{|T+1|-k}(\binom{|T|-1}{k-1}+\binom{|T-1|}{k-2})min(T)
∑T⊆S(−1)∣T+1∣−k(k−1∣T∣)min(T)=∑T⊆S(−1)∣T+1∣−k((k−1∣T∣−1)+(k−2∣T−1∣))min(T)
所以
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=fi−1,j−pi,k−1−fi−1,j−pi,k
#include<bits/stdc++.h>
#define N 10050
using namespace std;
typedef long long ll;
const int Mod = 998244353;
ll add(ll a, ll b){ return (a + b) % Mod;}
ll mul(ll a, ll b){ return (a * b) % Mod;}
ll power(ll a, ll b){ll ans = 1; for(;b;b>>=1, a=mul(a,a)) if(b&1) ans = mul(ans,a); return ans;}
ll f[2][N][11]; int n, k, m, p[N];
int main(){
scanf("%d%d%d", &n, &k, &m); k = n - k + 1;
for(int i = 1; i <= n; i++) scanf("%d", &p[i]);
int now = 0;
f[now][0][0] = 1;
for(int i = 1; i <= n; i++){
now ^= 1; memset(f[now], 0, sizeof(f[now]));
f[now][0][0] = 1;
for(int j = 1; j <= p[i] - 1; j++) for(int l = 1; l <= k; l++) f[now][j][l] = f[now^1][j][l];
for(int j = p[i]; j <= m; j++) for(int l = 1; l <= k; l++)
f[now][j][l] = add(f[now^1][j][l], add(f[now^1][j-p[i]][l-1], Mod - f[now^1][j-p[i]][l]));
}
ll ans = 0;
for(int i = 1; i <= m; i++) ans = add(ans, mul(f[now][i][k], mul(power(i, Mod-2), m)));
cout << ans; return 0;
}