min-max容斥


min-max容斥(包含kth)

用途

對於一個集合S,給出每個元素出現的概率,我們需要求每一個元素都出現至少一次的期望次數,可以使用min-max容斥,也可以求任意\(k\)個元素出現的期望(kth min-max容斥)。

例題

HDU-4336 Card Collector

這題當然可以狀壓dp,注意可能隨機到本身有的元素的情況即可。時間復雜度\(O(2^n*n)\),空間復雜度\(O(2^n)\)
但是,用以下方法時空效率都會更高,時間復雜度\(O(2^n)\),空間復雜度是\(O(n)\)的,並且非常好寫。

定義

對於一個集合S,一個元素的大小定義為它首次出現的時間
\(min(S)\)表示這個集合最小的元素。
\(max(S)\)表示這個集合最大的元素。
\(P_i\)表示\(i\)號元素出現的概率,\(E\)則表示期望次數。
顯然\(P(min(S))=\sum_{i\in S} P_i\),
\(E(min(S))=\frac{1}{P(min(S))}\)(這個很顯然,也比較好證明)
然后有一個結論:\(E(max(S))=\sum_{S'\subseteq S} E(min(S'))*(-1)^{|S'|+1}\) 
而對於這個問題我們要求的就是\(E(max(S))\),所以暴力搞一下就好。
時間復雜度\(O(2^n)\),但空間為\(O(20)???\)
ps:這道題每個元素之間相互獨立,如果元素之間不獨立但能求出每個子集的\(E(min(S'))\),也就是至少出現一個元素的期望次數,也能用min-max容斥,例如[HAOI2015]按位或,把每一個二進制位看做一個元素,他們本來不相互獨立,但我們可以用FWT求出每個集合的min之后套公式求全集的max

完整代碼

#include<bits/stdc++.h>
using namespace std;
const int N=21;
double a[N],ans;
int n;
void dfs(int x,double p,int k){
	if(x>n){if(p>=1e-9)ans+=(double)k/p;return;}//注意特判P為0的情況
	dfs(x+1,p,k);
	dfs(x+1,p+a[x],-k);
}
int main(){
	while(scanf("%d",&n)!=EOF){
		ans=0;
		for(int i=1;i<=n;++i)scanf("%lf",&a[i]);
		dfs(1,0,-1);
		printf("%.10lf\n",ans);
	}
	return 0;
}

kth min-max容斥

上述公式只能求最大元素出現的期望步數

min-max還可以用來求第\(k\)大元素(也就是至少出現\(n-k+1\)個元素)出現的期望步數。

先說結論:\(kthmax(S)=\sum_{T\subseteq S}(-1)^{|T|-k}C_{|T|-1}^{k-1}min(T)\)

可以發現上面的公式就是這個公式的特殊情況,把\(k=1\)帶入即可。

證明先咕一段時間,以后再補,然而用它做題也不需要證明

給個例題

重返現世

本題將公式套上可得

\(ans=\sum_{T\subseteq S}(-1)^{|T|-k}C_{|T|-1}^{k-1}\frac{m}{sum(T)}\)

其中\(sum(T)=\sum_{i\in T}p_i\)

\(f[i][j][x]\)表示前\(i\)個數選了\(sum(T)\)\(j\),且將\(k=x\)帶入之后前面那一串系數的和。

利用組合數優秀的性質進行轉移。

\(C_n^m=C_n^{n-m}\)

\(C_n^m=C_{n-1}^m+C_{n-1}^{m-1}\)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM