骰子期望

扔n个骰子,第i个骰子有可能投掷出Xi种等概率的不同的结果,数字从1到Xi。所有骰子的结果的最大值将作为最终结果。求最终结果的期望。

链接:https://www.nowcoder.com/questionTerminal/86ef0d5042934ef7819035794377a507?orderByHotValue=1&page=1&onlyReference=false

输入描述:

第一行一个整数n,表示有n个骰子。(1 <= n <= 50)
第二行n个整数,表示每个骰子的结果数Xi。(2 <= Xi <= 50)

输出描述: 

输出最终结果的期望,保留两位小数。

示例1

输入

2
2 2

输出

1.75

分析:这道题本身是蛮简单的,但比较难理解的是题意,主要考察概率论的知识。为了方便分析,我以三个骰子为例:例如Xi所给定的输入依次为:X1 = 3, X2 = 2,X3 = 3

那么我们可以取到的结果如下:

1 :  假设这三个骰子当中取到的最大值为1,则第一个骰子只能选择一种,第二个骰子只能选择一种,第三个骰子只能选择一种,即共有 1 * 1 * 1 = 1 种情况

2: 同理,假设这三个骰子当中取到的最大值为2, 则第一个骰子可以选择2种(1或者2),第二个骰子可以选择2种,第三个骰子可以选择2种,我们要排除 1 1 1 这种情况,因为当前取到的最大值为2,即至少有一个骰子取值为2,共有 2*2*2 - 1*1*1 = 7种可能

3:同理,假设这三个骰子当中取到的最大值为3,则第一个骰子可以选择3种(1或者2或者3),第二个骰子可以选择2种(最大值只能到2),第二个骰子可以选择3种,排除最大值为2的情况,即共有 3*2*3 - 2*2*2 = 10 种情况。

所有骰子出现的情况共有:3*2*3=18种。

取到1的可能性为: 1 / 18; 取到2的可能性为: 7 / 18;取到3的可能性为: 10 / 18;

根据高中概率论的知识即可求解出期望:1 * 1 / 18 + 2 * 7 / 18 + 3 * 10 / 18

特别注意的一点是:数据类型取double,int部分结果会溢出,而且很难找出原因。具体代码如下:

#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;

class solution {
public:
    double getMaxException(vector<int>& values, const int maxValue) {
        double allPossibleNum = 1;
        for (int& value: values) allPossibleNum *= value;
        double res = 0.0;
        for (int curValue = 1; curValue <= maxValue; ++curValue) {
            double cnt = 0, cur_mul = 1, pre_mul = 1;
            for (auto& value: values) {
                cur_mul *= min(value, curValue);
                pre_mul *= min(value, curValue - 1);
            }
            cnt =  cur_mul - pre_mul;  //获取取到Xi对应的所有可能结果
            res += curValue * cnt / allPossibleNum;
        }
        
        return res;
    }
};

int main() {
    int N;
    cin >> N;
    vector<int> values(N, 0);
    int maxValue = 0;
    for (int pos = 0; pos < N; ++pos) {
        cin >> values[pos];
        maxValue = max(maxValue, values[pos]);
    }
    
    printf("%.2f\n", solution().getMaxException(values, maxValue));
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值