期望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]∗(1−pa−pb)+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容斥
#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);
}
}