HDU-5985-Lucky Coins-2016青岛站D题-数学推导

题目链接
题目大意:给你n种硬币,并给你每种硬币的个数和正面朝上的概率。每次将所有的硬币投掷一下。背面朝上的抛弃。直到只剩下一种硬币或者没有硬币。最后剩下的那种硬币叫幸运硬币,问每种硬币成为幸运硬币的概率。
思路:令两个函数 f[i][k] 表示第i种硬币第K步死光的概率,所以 f[i][k]=(1?pki)ni
revf[i][k] 表示第i种硬币第k步至少有一个活着所以 revf[i][k]=1?f[i][k]
ans[i]=∑k=1100∑j=1,j!=in(rev[i][k]?rev[i][k+1])?f[j][k?1]此式子的意思是算第i个答案的时候,枚举步数,为了排除重复,把第i种硬币,当且至少有一个硬币活到第k步(k+1)步死的概率和其他硬币再第k步全死了的概率乘起来。

#include #define maxn 20 using namespace std; int a[maxn]; double p[maxn]; double f[maxn][111]; double revf[maxn][111]; double ans[maxn]; double POW(double x,int n) { double ans=1.0; while(n) { if(n&1) { ans*=x; } x*=x; n/=2; } return ans; } int main() { int t,n; scanf("%d",&t); while(t--) { memset(f,0,sizeof f); memset(revf,0,sizeof revf); scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d%lf",&a[i],&p[i]); } if(n==1) { printf("1.000000\n"); continue; } for(int i=1; i<=n; i++) { for(int k=1; k<=100; k++) { double temp=POW(p[i],k); temp=POW(1-temp,a[i]); f[i][k]=temp; revf[i][k]=1-temp; } } /*for(int i=1; i<=n; i++) { for(int k=1; k<=5; k++) { cout << f[i][k] << " "; } cout << endl; } for(int i=1; i<=n; i++) { for(int k=1; k<=5; k++) { cout << revf[i][k] << " "; } cout << endl; }*/ memset(ans,0,sizeof ans); for(int i=1; i<=n; i++) { for(int k=1; k<=99; k++) { double temp=1.0; for(int j=1; j<=n; j++) { if(i==j) continue; temp*=f[j][k]; //if(k<=5) { //cout << i << " " << j << " " << k << " " ; //cout << revf[i][k]*(f[j][k]-f[j][k-1]) << " " << endl; //} } if(k<=5) { //cout << i << " " << k << " " << temp<< " " << revf[i][k] << endl; //cout << revf[i][k]*temp << endl; //} ans[i]+=(revf[i][k]-revf[i][k+1])*temp; } } for(int i=1; i

    推荐阅读