题意:
给你n种硬币,并给你每种硬币的个数和正面朝上的概率。每次将所有的硬币投掷一下,背面朝上的抛弃。直到只剩下一种硬币或者没有硬币。最后剩下的那种硬币叫幸运硬币,问每种硬币成为幸运硬币的概率。
题解:
die[i][j]:第i种硬币在第k步之前(包括第k步)全部被淘汰的概率;
num[i]:第i种硬币的个数;
将num[i]个硬币分离为单独的,一个一个考虑;
一步胜
两步胜
……
k步胜
因为die[][]和alive[][]相当于前缀和,则求ans[i]时,需要第k个减去第k-1个,排除重复。
AC代码:
#include <bits/stdc++.h>
#define maxn 200
using namespace std;
int num[maxn];
double p[maxn];
double die[maxn][maxn];
double alive[maxn][maxn];
double ans[maxn];
double POW(double x,int n)
{
double ans=1.0;
while(n)
{
if(n%2==1)
ans*=x;
x*=x;
n/=2;
}
return ans;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
memset(ans,0,sizeof(ans));
memset(die,0,sizeof(die));
memset(alive,0,sizeof(alive));
memset(p,0,sizeof(p));
memset(num,0,sizeof(num));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%lf",&num[i],&p[i]);
}
if(n==1)
{
printf("1.000000\n");
continue;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=100;j++)
{
double temp=1-POW(p[i],j);
die[i][j]=POW(temp,num[i]);
alive[i][j]=1.0-die[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int k=1;k<100;k++)
{
double temp=alive[i][k]-alive[i][k+1];
for(int j=1;j<=n;j++)
{
if(i!=j)
temp*=die[j][k];
}
ans[i]+=temp;
}
if(i==1)
printf("%.6lf",ans[i]);
else
printf(" %.6lf",ans[i]);
}
printf("\n");
}
return 0;
}