关于 min-max 容斥学习笔记_#include容斥,我们希望构造一个系数使得
min-max 容斥学习笔记_c++_02
考虑 min-max 容斥学习笔记_c++_03 大的贡献
min-max 容斥学习笔记_c++_04
反演得 min-max 容斥学习笔记_i++_05
所以 min-max 容斥学习笔记_c++_06

关于 min-max 容斥学习笔记_#include_07 容斥,同上考虑 min-max 容斥学习笔记_c++_08 大的贡献
min-max 容斥学习笔记_#include_09
反演得 min-max 容斥学习笔记_#include_10
所以 min-max 容斥学习笔记_c++_11


HDU4624:Endless Spin
题意:给一个长为m 的白球序列,每次随机一个区间,把区间内的球全部染为黑色,求把所有球染黑的期望步数
考虑到 min-max 容斥学习笔记_#include_12不好求,转换为求 min-max 容斥学习笔记_#include_13 然后反演
一个集合的最小期望就是这个集合第一个被染到的点的期望时间
发现为 总个数/能覆盖一个点的区间个数
但我们不能枚举集合,考虑到能覆盖到一个点的区间个数很少,想到了 min-max 容斥学习笔记_c++_14
min-max 容斥学习笔记_c++_15 为当前选到了第 i 个位置,不能覆盖一个点的个数是 j,最后一维是容斥的系数
min-max 容斥学习笔记_i++_16

#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;
}

​重返现世​​​

min-max 容斥学习笔记_#include_17
考虑到 min-max 容斥学习笔记_#include_18很小,于是把min-max 容斥学习笔记_#include_19换成 min-max 容斥学习笔记_#include_20,变成求 min-max 容斥学习笔记_#include_21
min-max 容斥学习笔记_#include_22
min-max 容斥学习笔记_i++_23
同样又不能枚举集合,而 min-max 容斥学习笔记_c++_24 的个数非常少
于是令 min-max 容斥学习笔记_c++_25 表示到第 i 个,当前min-max 容斥学习笔记_i++_26 的和,现在求的是第 k 大的min-max 容斥学习笔记_i++_27的值
如果不选 min-max 容斥学习笔记_c++_28
如果选,所有的 min-max 容斥学习笔记_#include_29 要变成 min-max 容斥学习笔记_c++_30
也就是 min-max 容斥学习笔记_i++_27变成 min-max 容斥学习笔记_i++_32
min-max 容斥学习笔记_#include_33
所以 min-max 容斥学习笔记_#include_34

#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;
}