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; }