WannaflyUnion挑战赛6 B比赛

本文分享了一道关于计算解题概率的题目解析过程及Java与C++代码实现。作者通过对比官方题解和个人理解,详细阐述了如何正确计算每道题目被解答成功的概率,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

题目链接

Markdown

我这次很难得把题目放上来,是因为我真的想吐槽一下自己的语文。

题意理解

我的思路和官方题解思路是一致的,但是由于是用的Java写的,我不知道怎么枚举,就用了dfs,实际效果是一样的。

官方题解

算出一个题被做出来的概率,然后 212 枚举一下每个题是否被做出来,算算贡献

我的理解

首先这题,是说你做出来总共0题-12题的概率,这点我一开始没有反应过来。后面被坑到的人更多。

其次,对于题目 i ,你解不出来的概率应该是(1a[i])(1b[i])(1c[i]) ,这时候用1一减就出来了。不应该选择这样的公式进行计算: a[i]+(1a[i])(b[i]+c[i]) 。我真的,不知道为什么自己会想到第二个公式。

等公式推出来了,其实就很好写了。

代码

import java.math.BigDecimal;
import java.util.Scanner;

public class Main {
    static BigDecimal[] a = new BigDecimal[13];
    static BigDecimal[] b = new BigDecimal[13];
    static BigDecimal[] c = new BigDecimal[13];
    static BigDecimal[] pro = new BigDecimal[13];
    static boolean[] passed = new boolean[13];

    static void dfs(int n) {
        if (n == 13) {
            BigDecimal temp = new BigDecimal(1);
            int cnt = 0;
            for (int i = 1; i < 13; i++) {
                if (passed[i]) {
                    cnt++;
                    temp = temp.multiply(a[i]);
                } else {
                    temp = temp.multiply(BigDecimal.ONE.subtract(a[i]));
                }
            }
            pro[cnt] = pro[cnt].add(temp);
            return;
        }
        passed[n] = true;
        dfs(n + 1);
        passed[n] = false;
        dfs(n + 1);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        a[0] = BigDecimal.ZERO;
        for (int i = 1; i < 13; i++) {
            a[i] = scanner.nextBigDecimal();
        }
        b[0] = BigDecimal.ZERO;
        for (int i = 1; i < 13; i++) {
            b[i] = scanner.nextBigDecimal();
        }
        c[0] = BigDecimal.ZERO;
        for (int i = 1; i < 13; i++) {
            c[i] = scanner.nextBigDecimal();
        }
        scanner.close();
        for (int i = 0; i < 13; i++) {
            a[i] = a[i].add(BigDecimal.ONE.subtract(a[i]).multiply(b[i]));
            a[i] = a[i].add(BigDecimal.ONE.subtract(a[i]).multiply(c[i]));
        }
        for (int i = 0; i < 13; i++) {
            pro[i] = BigDecimal.ZERO;
        }
        dfs(1);
        for (int i = 0; i < 13; i++) {
            System.out.printf("%f\n", pro[i]);
        }
    }
}

补充内容

关于暴力枚举的部分,应该是我昨晚失了智。其实用Java和用cpp在枚举上相差不大。还是写一下吧。

#include <cstring>
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iomanip>
#include <vector>

using namespace std;
double a[13];
double b[13];
double c[13];
double pro[13];
double pass[13];
int main() {
    for(int i = 0; i < 12; i++) {
        scanf("%lf", &a[i]);
    }
    for(int i = 0; i < 12; i++) {
        scanf("%lf", &b[i]);
    }
    for(int i = 0; i < 12; i++) {
        scanf("%lf", &c[i]);
        pass[i] = 1 - (1 - a[i]) * (1 - b[i]) * (1 - c[i]);
    }
    for(int i = 0; i < 13; i++) {
        pro[i] = 0;
    }
  // i表示2^12种可能性
    for(int i = 0; i < (1 << 12); i++) {
        double temp = 1.0;
        int cnt = 0;
      // j表示题目数
        for(int j = 0; j < 12; j++) {
            if((i >> j) & 1) {
                temp *= pass[j];
                cnt++;  
            } else {
                temp *= (1 - pass[j]);
            }
        }
        pro[cnt] += temp;
    }
    for(int i = 0; i < 13; i++) {
        printf("%6lf\n", pro[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值