5985(Lucky Coins )數學·概率·公式推導
阿新 • • 發佈:2018-12-13
題意:
給你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; }