Card Collector HDU - 4336

Card Collector HDU - 4336

ans[S]表示获得S的卡片次数的期望
考虑到达S前一次的卡片
1.获得一张已获得的 期望是ans[S]*sum{p[i]|i在S中}
2.获得一张未获得的 期望是sum{ans[S-i]*p[i]|i在S中}
3.未获得卡片 期望是ans[S]*p[0]
因此ans[S]=ans[S]*(p[0]+sum{p[i]|i在S中})+sum{ans[S-i]*p[i]|i在S中}
ans[S]*(1-p[0]-sum{p[i]|i在S中})=sum{ans[S-i]*p[i]|i在S中}
ans[S]=sum{ans[S-i]*p[i]|i在S中}/(1-p[0]-sum{p[i]|i在S中})

X=ans[S]
Y=sum{(ans[S-i]+1)*p[i]|i在S中} 即获得一个未得的卡对期望的贡献
P2=p[0]+sum{p[i]|i在S中}) 即获得已得的卡或无卡的概率
那么Y+P2*(X+1)=X
P2*X+P2+Y=X
P2+Y=(1-P2)*X
X=(P2+Y)/(1-P2)

ans[S]表示全0到S所用步数的期望
考虑到达S前一次的卡片
1.未获得卡片/获得一张已获得的卡片 期望是(p[0]+sum{p[S的某一个]})*(ans[S]+1)
01 0.6x+0.6 10 0.9x+0.9
2.获得一张未获得的 期望是sum{p[S的某一个]*(ans[S-S的某一个]+1)}
01 0.1 10 0.4(错误答案花费7个小时)

以上全部都是错的。直觉上会让人想到将ans[S]定义为获得S的卡片的购买包数的期望,然而由于即使一包也不买,这个期望也不为0,导致非常难处理。

更好的方法是定义ans[S]为获得S的卡片到全部获得所用步数的期望。p[0]表示买一包不获得卡片的概率。考虑S状态后下一步:

1.未获得卡片/获得一张已获得的卡:期望是$(p[0]+sum\{p[S的某一个]\})*(ans[S]+1)$

样例1:0.9*11=9.9
样例2:

10 (0.5+0.4)*(ans[2]+1)
01 (0.5+0.1)*(ans[1]+1)
00 (0.5)*(ans[0]+1)

2.获得一张未获得的:期望是$sum\{p[S以外的i]*(ans[S+i]+1)\}$

样例1:0.1*1=0.1
样例2:
10 0.1*1=0.1
ans[2]=10
01 0.4*1=0.4
ans[1]=2.5
00 0.1*(ans[1]+1)+0.4*(ans[2]+1)=4.75
ans[0]=10.5

$(p[0]+sum\{p[S的某一个]\})*(ans[S]+1)+sum\{p[S以外的i]*(ans[S+i]+1)\}=ans[S]$

$(p[0]+sum\{p[S的某一个]\})*ans[S]+p[0]+sum\{p[S的某一个]\}+sum\{p[S以外的i]*(ans[S+i]+1)\}=ans[S]$

$(1-(p[0]+sum{p[S的某一个]}))*ans[S]=p[0]+sum{p[S的某一个]}+sum{p[S以外的i]*(ans[S+i]+1)}$

$ans[S]=(p[0]+sum\{p[S的某一个]\}+sum\{p[S以外的i]*(ans[S+i]+1)\})/(1-(p[0]+sum\{p[S的某一个]\}))$

 1 #include<cstdio>
 2 #include<cstring>
 3 double p[22],ans[1100000],tt;
 4 int n;
 5 int main()
 6 {
 7     int i,j;
 8     while(scanf("%d",&n)==1)
 9     {
10         p[0]=0;
11         for(i=1;i<=n;i++)
12         {
13             scanf("%lf",&p[i]);
14             p[0]+=p[i];
15         }
16         p[0]=1-p[0];
17         memset(ans,0,sizeof(ans));
18         for(i=(1<<n)-2;i>=0;i--)
19         {
20             tt=p[0];
21             for(j=1;j<=n;j++)
22                 if(i&(1<<(j-1)))
23                     tt+=p[j];
24                 else
25                     ans[i]+=p[j]*(ans[i|(1<<(j-1))]+1);
26             ans[i]+=tt;
27             ans[i]/=(1-tt);
28         }
29         printf("%lf\n",ans[0]);
30     }
31     return 0;
32 }

http://blog.csdn.net/a1061747415/article/details/34481361

http://www.cnblogs.com/six-god/p/3580242.html

posted @ 2017-10-07 20:33  hehe_54321  阅读(258)  评论(0编辑  收藏  举报
AmazingCounters.com