洛谷P2111考场奇遇

题目描述

/*
刚读完题
呀,这不是个数学题吗
二项分布呀
求出小红每题得分的概率,然后用二项分布的公式
然后,思路很清晰了,先把大体框架写完....

写完主函数后
发现
C(50,x)
这组合数怎么求QwQ
百分之百爆long long啊
前半部分组合数爆long long,后半部分乘方损精度
这做法大概没救了
*/

那份没救了的代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,A,q;
int tot;
double double_pow(double a,int b){
    double mul=1.0;
    while(b){
        if(b) mul=mul*a;
        a=a*a;
    }
    return mul;
}
int main(){
    scanf("%d%d%d",&n,&A,&q);
    string ss;cin>>ss;
    for(int i=0;i<n;i++)
        if(ss[i]=='1') tot++;
    double correct=1.0*A/100.0*tot/n + (1.0-A)/100.0*(n-tot)/n;
    double wrong=1.0-correct;
    double ans=0.0;
    for(int i=0;i<=n-q;i++){
        double res=1.0*C(n,i);
        res*=double_pow(wrong,i)*double_pow(correct,n-i);
        ans+=res;
    }
    printf("%.3f\n",ans);
    return 0;
}

附正解

/*
递推
F[i][j]:前i道题对j道的概率
考虑每道题做对与做错对f的贡献
*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,q;
double f[55][55];
double a;
int main(){
    scanf("%d%lf%d",&n,&a,&q);a/=100.0;
    if(!q){
        printf("1.000\n");
        return 0;
    }
    string ss;cin>>ss;
    f[0][0]=1.0;
    for(int i=1;i<=n;i++){
        if(ss[i-1]=='1') f[i][0]=f[i-1][0]*(1.0-a);
        else f[i][0]=f[i-1][0]*a;
        for(int j=1;j<=i;j++){
            if(ss[i-1]=='1') f[i][j]=f[i-1][j]*(1.0-a)+f[i-1][j-1]*a;
            else f[i][j]=f[i-1][j]*a+f[i-1][j-1]*(1.0-a);
        }
    }
    double ans=0.0;
    for(int i=n;i>=q;i--) ans+=f[n][i];
    printf("%.3f\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/aptx--4869/p/9919265.html
今日推荐