【HDU4336】Card Collector(Min-Max容斥)


【HDU4336】Card Collector(Min-Max容斥)

題面

Vjudge

題解

原來似乎寫過一種狀壓的做法,然后空間復雜度很不優秀。
今天來補一種神奇的方法。


給定集合\(S\),設\(max\{S\}\)\(S\)中的最大值,\(min\{S\}\)為集合\(S\)中的最小值。
那么我們可以得到:
\(max\{S\}=\sum_{T\subseteq S}(-1)^{|T|+1}min\{T\}\)
證明的話,大概就是如果你欽定一個最小值,並且它強制出現,
如果枚舉所有子集,不難證明除了最大值之外,任何一個數的出現次數都是\(2^k\)的形式。
並且子集大小的奇偶性一一對應。因此,除了最大值之外,任何一個值的貢獻全部會互相抵消,最后剩下的值就只有最大值。

對於期望而言這樣做也是正確的。


回到這道題目,我們\(max\{S\}\)表示集合中最晚出現的元素,\(min\)同理。
\(E(max\{S\})\)表示出現時間的期望。
那么我們要求的是\(E(max\{\)全集\(\})\),那么利用\(min-max\)容斥,有:
\(E(max\{S\})=\sum_{T\subseteq S}(-1)^{|T|+1}E(min\{T\})\)
\(E(min\{T\})=\frac{1}{\sum_{i\in T}p_i}\)
那么枚舉子集,直接\(dfs\)實現就好了

#include<cstdio>
int n;
double p[20],ans;
void dfs(int x,double e,int opt)
{
	if(x>=n){if(e>1e-7)ans+=opt/e;return;}
	dfs(x+1,e,opt);dfs(x+1,e+p[x],-opt);
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		for(int i=0;i<n;++i)scanf("%lf",&p[i]);
		ans=0;dfs(0,0,-1);
		printf("%.6lf\n",ans);
	}
}


免責聲明!

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



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