# 【Learning】min-max容斥以及推广

### min-max容斥

$max\left(S\right)=\sum _{T\subseteq S}\left(-1{\right)}^{|T|-1}min\left(T\right)$

$max\left(S\right)=\sum _{T\subseteq S}f\left(|T|\right)min\left(T\right)$

$\left[x==0\right]=\sum _{i=0}^{x}{C}_{x}^{i}×f\left(i+1\right)$

$f\left(x+1\right)=\sum _{i=0}^{x}\left(-1{\right)}^{x-i}{C}_{x}^{i}\left[i==0\right]$

$f\left(x+1\right)=\left(-1{\right)}^{x}$

$f\left(x\right)=\left(-1{\right)}^{x-1}$

$max\left(S\right)=\sum _{T\subseteq S}f\left(|T|\right)min\left(T\right)\phantom{\rule{0ex}{0ex}}=\sum _{T\subseteq S}\left(-1{\right)}^{|T|-1}min\left(T\right)$

### hdu4336 Card Collector

$max\left(S\right)=\sum _{T\subseteq S}\left(-1{\right)}^{|T|-1}min\left(T\right)$

$min\left(T\right)=\frac{1}{\sum _{i\in T}{P}_{i}}$

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=25;
const double eps=1e-7;
double a[N],ans;
int n;
void dfs(int now,int tot,double sum){
if(now>n){
if(sum>eps){
if(tot&1){
ans+=1/sum;
}else{
ans-=1/sum;
}
}
return;
}
dfs(now+1,tot,sum);
dfs(now+1,tot+1,sum+a[now]);
}
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++){
scanf("%lf",&a[i]);
}
ans=0;
dfs(1,0,0);
printf("%lf\n",ans);
}
return 0;
}

### bzoj4036 按位或

$max\left(S\right)=\sum _{T\subseteq S}\left(-1{\right)}^{|T|-1}min\left(T\right)$

$min\left(S\right)=\frac{1}{\sum _{T\cap S\ne \mathrm{\varnothing }}{P}_{T}}$

$\sum _{T\cap S\ne \mathrm{\varnothing }}{P}_{T}\phantom{\rule{0ex}{0ex}}=sum-\sum _{T\cap S=\mathrm{\varnothing }}{P}_{T}\phantom{\rule{0ex}{0ex}}=sum-\sum _{T\cap \left(all-S\right)=\left(all-S\right)}{P}_{T}$

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1050005;
int n,all,tmp,cnt[N];
double sum,res,ans,a[N];
int main(){
scanf("%d",&n);
all=1<<n;
for(int i=0;i<all;i++){
cnt[i]=cnt[i>>1]+(i&1);
scanf("%lf",&a[i]);
sum+=a[i];
if(fabs(a[i])>1e-6){
tmp|=i;
}
}
if(tmp!=all-1){
puts("INF");
return 0;
}
for(int i=1;i<all;i<<=1){
for(register int j=0;j<all;j+=(i<<1)){
for(register int k=j;k<j+i;k++){
a[k+i]+=a[k];
}
}
}
for(register int i=0;i<all;i++){
res=sum-a[all-1-i];
if(res>1e-6){
res=1/res;
}else{
res=0;
}
if(cnt[i]&1){
ans+=res;
}else{
ans-=res;
}
}
printf("%.8lf\n",ans);
return 0;
}

### 推广 kth min-max容斥

$kthmax\left(S\right)=\sum _{T\subseteq S}f\left(|T|\right)min\left(T\right)$

$\left[x==k-1\right]=\sum _{i=0}^{x}{C}_{x}^{i}×f\left(i+1\right)$

$f\left(x+1\right)=\sum _{i=0}^{x}\left(-1{\right)}^{x-i}{C}_{x}^{i}\left[i==k-1\right]$

$f\left(x+1\right)=\left(-1{\right)}^{\left(x-\left(k-1\right)\right)}{C}_{x}^{k-1}$

$f\left(x\right)=\left(-1{\right)}^{x-k}{C}_{x-1}^{k-1}$

$kthmax\left(S\right)=\sum _{T\subseteq S}f\left(|T|\right)min\left(T\right)\phantom{\rule{0ex}{0ex}}=\sum _{T\subseteq S}\left(-1{\right)}^{|T|-k}{C}_{|T|-1}^{k-1}min\left(T\right)$