HDU4336:Card Collector(min-max容斥)


題面

傳送門

Sol

方法一

直接狀壓就好了

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;

int n;
double p[21], f[1 << 20];

int main(RG int argc, RG char *argv[]){
	while(scanf("%d", &n) != EOF){
		for(RG int i = 1; i <= n; ++i) scanf("%lf", &p[i]);
		RG int S = 1 << n; Fill(f, 0);
		for(RG int i = S - 2; ~i; --i){
			RG double s = 1.0;
			for(RG int j = 1; j <= n; ++j) if(~i & (1 << (j - 1))) s -= p[j];
			s = 1.0 - s, f[i] = 1.0 / s;
			for(RG int j = 1; j <= n; ++j)
				if(~i & (1 << (j - 1))) f[i] += p[j] * f[i | (1 << (j - 1))] / s;
		}
		printf("%.6lf\n", f[0]);
	}
    return 0;
}

方法二

方法一實在太水了,顯然不是重點
下面介紹一種容斥方法

min-max容斥

\(E[max(S)]=\sum(-1)^{k+1}E[min(S')]\)
其中集合\(S'\subseteq S\)\(k=|S'|\)

\(max(S)\)指的是這個集合內最后出現的元素
\(min(S)\)指的是這個集合內最先出現的元素
\(E\)表示期望第幾步出現

具體到這個題
就是要求\(E[max(\)全集\()]\)
\(E[min(S')]\)就是指\(S'\)任意出現一個的期望步數
舉例:
每步出現\(x_i\)的概率\(p_i\)
\(min\{x_1, x_2, x_3 \}\)的概率就是\(p_1+p_2+p_3\)
期望步數就是\(\frac{1}{p_1+p_2+p_3}\)

然后就容斥一下這個題

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;

int n;
double p[21], ans;

IL void Dfs(RG int x, RG double E, RG int op){
	if(x > n){
		if(E > 1e-7) ans += 1.0 * op / E;
		return;
	}
	Dfs(x + 1, E, op);
	Dfs(x + 1, E + p[x], -op);
}

int main(RG int argc, RG char *argv[]){
	while(scanf("%d", &n) != EOF){
		for(RG int i = 1; i <= n; ++i) scanf("%lf", &p[i]);
		ans = 0, Dfs(1, 0, -1);
		printf("%.6lf\n", ans);
	}
    return 0;
}


免責聲明!

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



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