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

题目链接

题目大意:给你n种硬币,并给你每种硬币的个数和正面朝上的概率。每次将所有的硬币投掷一下。背面朝上的抛弃。直到只剩下一种硬币或者没有硬币。最后剩下的那种硬币叫幸运硬币,问每种硬币成为幸运硬币的概率。

思路:令两个函数 f[i][k] 表示第i种硬币第K步死光的概率,所以
f[i][k]=(1pki)ni

revf[i][k] 表示第i种硬币第k步至少有一个活着所以
revf[i][k]=1f[i][k]

ans[i]=k=1100j=1,j!=in(rev[i][k]rev[i][k+1])f[j][k1]

此式子的意思是算第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;iprintf("%.6f ",ans[i]);
        }
        printf("%.6f\n",ans[n]);
    }
    return 0;
}

你可能感兴趣的:(数学推导)