题目大意不多说了
这里用dp[i][0] 代表取完第一个盒子后第二个盒子剩 i 个的概率,对应期望就是dp[i][0] *i
dp[i][1] 就代表取完第二个盒子后第一个盒子剩 i 个的概率
dp[i][0] = p^(n+1) * (1-p)^(n-i) * C(2*n-i , n-i) = p^(n+1) * (1-p)^(n-i) * (2*n-i)! / (n-i)! / n!
dp[i+1][0] = p^(n+1) * (1-p)^(n-i-1) * C(2*n-i-1 , n-i-1) = p^(n+1) * (1-p)^(n-i-1) * (2*n-i-1)! / (n-i-1)! / n!
dp[i][0] = dp[i+1][0] * (1-p) * (2*n-i) / (n-i)
dp[i][1]也是一样的道理
如果一开始给dp[n][0] 赋初值 pow(p,n+1) 那么如果n过大,那么因为精确度问题得到的是0
所以n+1个p在计算过程中在答案超过总数时一个一个往里乘
#include
#include
#include
using namespace std;
const int N = ;
double dp[N][];
int main()
{
// freopen("test.in","rb",stdin);
int n,cas = ;
double p;
while(scanf("%d%lf",&n,&p)!=EOF){
double ans1 = ;
double ans2 = ;
int last\[\];
last\[\] = last\[\] = n+;
double q = -p;
dp\[n\]\[\] = ;
dp\[n\]\[\] = ;
ans1 += n;
ans2 += n;
for(int i=n-;i>=;i--){
double tmp1 = q \* (\*n-i) / (n-i);
double tmp2 = p \* (\*n-i) / (n-i);
//递推过程,因为数目太多,p直接开方,数据大点的话就直接因精确度不够变为0
//所以每次在答案超过总数的情况下乘个p值
dp\[i\]\[\] = tmp1 \* dp\[i+\]\[\];
dp\[i\]\[\] = tmp2 \* dp\[i+\]\[\];
ans1 += (dp\[i\]\[\] \* i);
while(ans1>n){
dp\[i\]\[\] \*= p;
ans1 \*= p;
last\[\]--;
}
ans2 += (dp\[i\]\[\] \* i);
while(ans2>n){
dp\[i\]\[\]\*=q;
ans2 \*= q;
last\[\]--;
}
}
// cout<<" dp "<<dp\[n\]<<endl;
ans1 \*= pow(p,last\[\]);
ans2 \*= pow(q,last\[\]);
cas++;
printf("Case %d: %.6f\\n",cas,ans1+ans2);
}
return ;
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章