期望dp第三题.

这个还是老套路嘛,看到 n = 20 n=20 n=20想到状压所有状态

那么定义 d p [ x ] dp[x] dp[x]为卡片状态是 x x x时到达终点的期望

那么有 d p [ ( 1 < < n ) − 1 ] = 0 : dp[(1<<n)-1]=0: dp[(1<<n)1]=0:到了终点期望肯定是0嘛!!

至于转移, x x x可以从任何一个自己没有包含的卡片来转移

x x x不包含第 a , b a,b a,b张卡片

那么 d p [ x ] = d p [ x + ( 1 < < a ) ] ∗ p a + d p [ x + ( 1 < < b ) ] ∗ p b + d p [ x ] ∗ ( 1 − p a − p b ) + 1 dp[x]=dp[x+(1<<a)]*p_a+dp[x+(1<<b)]*p_b+dp[x]*(1-p_a-p_b)+1 dp[x]=dp[x+(1<<a)]pa+dp[x+(1<<b)]pb+dp[x](1papb)+1

右边的 d p [ x ] dp[x] dp[x]移项到左边即可

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,m,ok[1<<21];
double dp[1<<21],a[21];
int main()
{
	while( cin >> n )
	{
		for(int i=0;i<n;i++)	cin >> a[i];
		dp[(1<<n)-1]=0;
		for(int i=(1<<n)-2;i>=0;i--)
		{
			dp[i]=0;
			double temp=0;
			for(int j=0;j<n;j++)
			{
				if( !((1<<j)&i) )
				{
					int v=i+(1<<j);
					dp[i]+=dp[v]*a[j];
					temp+=a[j];
				}
			}
			temp=1-temp;//毫无作用概率是temp 
			dp[i]+=1;
		//	if( 1-temp!=0 )
				dp[i]/=(1-temp);
		}
		printf("%.5lf\n",dp[0]);
	}
} 

容斥原理

我猜你肯定没看懂为啥这样容斥

因为这是个特殊的名词叫做 m i n _ m a x min\_max min_max容斥

min_max容斥

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,m,ok[1<<21];
double dp[1<<21],a[21],ans;
int main()
{
	while( cin >> n )
	{
		ans=0;
		int last = (1<<n);
		for(int i=0;i<n;i++)	cin >> a[i];
		for(int i=1;i<last;i++)
		{
			double temp=0; int cnt=0;
			for(int j=0;j<n;j++)
				if( i&(1<<j) )	cnt++,temp+=a[j];
			if( cnt&1 )	ans+=1.0/temp;
			else	ans-=1.0/temp;
		}
		printf("%.5lf\n",ans);
	}
}