HDU 4336 容斥原理 || 状压DP

Posted on 2016-07-24 21:47  yyjxx2010xyu  阅读(89)  评论(0编辑  收藏  举报

状压DP :F(S)=Sum*F(S)+p(x1)*F(S^(1<<x1))+p(x2)*F(S^(1<<x2))...+1;

F(S)表示取状态为S的牌的期望次数,Sum表示什么都不取得概率,p(x1)表示的是取x1的概率,最后要加一因为有又多拿了一次.整理一下就可以了。

 1 #include <cstdio>
 2 const int Maxn=23;
 3 double F[1<<Maxn],p[Maxn];
 4 int n;
 5 int main()
 6 {
 7     while (scanf("%d",&n)!=EOF)
 8     {
 9         double Sum=0;
10         for (int i=1;i<=n;i++) scanf("%lf",&p[i]),Sum+=p[i];
11         F[0]=0; Sum=1-Sum; //Sum表示为空的概率. 状态位为1表示该张卡片还未取.
12         for (int i=1;i<(1<<n);i++)
13         {
14             double X=0,Ret=0;
15             for (int j=1;j<=n;j++)
16             {
17                 if (!(i&(1<<(j-1)))) X+=p[j]; 
18                 else Ret+=p[j]*F[i^(1<<(j-1))];
19             }
20             X=X+Sum;
21             F[i]=(Ret+1)/(1-X);
22         }
23         printf("%.5lf\n",F[(1<<n)-1]);
24     }
25     return 0;
26 }
状压DP

容斥原理: 若发生的概率为p,第一次发生的概率的期望是1/p,我感觉并不是很显然。

Prove:E=p+p(1-p)*2+p*(1-p)^2*3+...=pS

    S=1+(1-p)*2+(1-p)^3..=1/p^2

    ∴Ep=1

  那么两个发生的期望就为1/(p1+p2)

  三个发生的期望为1/(p1+p2+p3)

 1 #include <cstdio>
 2 const int Maxn=23;
 3 double F[1<<Maxn],p[Maxn];
 4 int n;
 5 int main()
 6 {
 7     while (scanf("%d",&n)!=EOF)
 8     {
 9         double Ans=0;
10         for (int i=1;i<=n;i++) scanf("%lf",&p[i]);
11         for (int i=1;i<(1<<n);i++)
12         {
13             double Sum=0; int cnt=0;
14             for (int j=1;j<=n;j++)
15                 if (i&(1<<(j-1)))
16                 {
17                     Sum+=p[j];
18                     cnt++;
19                 }
20             if (cnt&1) Ans+=1/Sum; else Ans-=1/Sum;
21         }
22         printf("%.5lf\n",Ans);
23     }
24     return 0;
25 }
容斥原理