kill(i,j)表示第i种硬币在第j轮或者之前就死光的概率,它等于(1-pi^j)^num(i)
rev(i,j)表示第i种硬币在j轮后仍然存活的概率,它等于1-kill(i,j)
然后对每种硬币i模拟100轮左右,每一轮答案要加上 在j轮后i仍然存活的概率*(在第j轮时其他恰好死光的概率《 这个值等于(∏(kill(j,k))-∏(kill(j,k-1)))(i!=j) 》)
注意,一定要特判n==1时输出1.000000,因为我们模拟时并没有考虑第0轮。
#include<cstdio>
using namespace std;
double Quick_Pow(double x,int k){
if(!k){
return 1;
}
double res=Quick_Pow(x,k>>1);
res*=res;
if(k&1){
res*=x;
}
return res;
}
int Zu,n,a[11];
double anss[11],p[11],rev[11][111],kill[11][111],kills[111];
int main(){
// freopen("d.in","r",stdin);
scanf("%d",&Zu);
for(int zu=1;zu<=Zu;++zu){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d%lf",&a[i],&p[i]);
}
if(n==1){
printf("%.6f
",1.0);
continue;
}
for(int i=1;i<=n;++i){
double pi_j=1;
for(int j=1;j<=100;++j){
pi_j*=p[i];
kill[i][j]=Quick_Pow(1.0-pi_j,a[i]);
rev[i][j]=1.0-kill[i][j];
}
}
for(int i=1;i<=n;++i){
for(int k=1;k<=100;++k){
kills[k]=1;
for(int j=1;j<=n;++j){
if(i!=j){
kills[k]*=kill[j][k];
}
}
}
anss[i]=rev[i][1]*kills[1];
for(int k=2;k<=99;++k){
anss[i]+=rev[i][k]*kills[k];
anss[i]-=rev[i][k]*kills[k-1];
}
anss[i]-=rev[i][100]*kills[99];
}
for(int i=1;i<n;++i){
printf("%.6lf ",anss[i]);
}
printf("%.6lf
",anss[n]);
}
return 0;
}