链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5985
题意:
有多种类型的硬币,每种类型的硬币都有一定的数量,现在每次抛硬币,除去朝下的硬币,知道最后只剩下一个硬币或者没有硬币,最后的硬币便是幸运硬币,求每种类型硬币成为幸运硬币的概率。
思路:
die[i][j]die[i][j] 表示第 ii 种硬币在前 jj 步内死光光的概率;
alive[i][j]alive[i][j] 表示第 ii 种硬币在第 jj 步还有至少一个没死的概率;
num[i]num[i] 表示第 ii 种硬币的个数;
p[i] 表示第 ii 种硬币投出正面的概率;
所以:
die[i][j]=(1−p[i]j)num[i]die[i][j]=(1−p[i]j)num[i]
alive[i][j]=1−die[i][j]alive[i][j]=1−die[i][j]
假如第 ii 种硬币在第 steps+1 步死光,那么第 i 种硬币为幸运硬币的概率为:
∑step(alive[i][step]−alive[i][step+1])∗∏nj=1(j==i?1:die[j][step]);
其实一直不理解为什么要用alive相减。可能是因为step+1是由step分下去的吧,换句话说,step步至少
有一个活,会分成在第step+1步全死或者step+1步至少一个活。
#include <bits/stdc++.h>
using namespace std;
int n,m,num;
double p;
double die[15][105],alive[15][105];
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n;
for(int i=1; i<=n; i++)
{
cin>>num>>p;
for(int k=1; k<=100; k++)
{
die[i][k] = pow(1.0-pow(p,k*1.0),num*1.0);
alive[i][k]=1.0-die[i][k];
}
}
if(n==1)
{
cout<<"1.000000"<<endl;
continue;
}
for(int i=1; i<=n; i++)
{
double ans = 0;
for(int k=1; k<=100; k++)
{
double temp =1;
for(int j=1; j<=n; j++)
{
if(i!=j)
temp*=die[j][k];
}
ans+=(alive[i][k]-alive[i][k+1])*temp;
}
printf("%.6f%c",ans,i==n?'\n':' ');
}
}
return 0;
}