试题:如何利用一个6面概率均匀的骰子把一个苹果公平地交给七个孩子中的某一个(上)

来源:互联网 发布:java去掉html标签样式 编辑:程序博客网 时间:2024/05/22 01:51
 

写作该文的目的是出于对帖子: 一个骰子有6面, 概率均匀, 我如何选择7件事? 有些疑问和想法

帖子中对8楼的方案呼声最高:

8楼的方案如下:

用一个骰子扔一次得到x, 再仍一次得到y, 如果x, y都为6就不算, 重来

该方案原理是利用表达式(6x-6+y)可以得到[1, 36], 再去除x, y都为6的情形, 得到[1, 35], 这35个数字对7取余后再加1, 就会得到5个1, 5个2, ..., 5个6, 5个7, 故认为((6x-6+y)%7)+1取得[1, 7]中各数的概率是相同的

我当时是这么想的:

U = { 1, 2, 3, 4, 5, 6, 7 }, y = { 1, 2, 3, 4, 5, 6 }, 当x = 6时, y != 6

x = 1,     ((6x-6+y)%7)+1 = U - { 1 },       第一个孩子分不到苹果

x = 2,     ((6x-6+y)%7)+1 = U - { 7 },       第七个孩子分不到苹果

x = 3,     ((6x-6+y)%7)+1 = U - { 6 },       第六个孩子分不到苹果

x = 4,     ((6x-6+y)%7)+1 = U - { 5 },       第五个孩子分不到苹果

x = 5,     ((6x-6+y)%7)+1 = U - { 4 },       第四个孩子分不到苹果

x = 6,     ((6x-6+y)%7)+1 = U - { 2, 3 },   第二个和第三个孩子分不到苹果

为什么x = 6时会使两孩子分不到苹果呢, 另外x, y调换下顺序得到的结果也是不一样的, 也就是说不能用两个骰子一起扔, 这似乎又与时间(顺序有关了), 想到这里我有些疑惑了

虽然有疑惑, 但我又表达不出来, 或者说根本讲不清楚我在疑惑什么, 只是觉得有点不对劲, 所以, 我只好用代码来证实下我的想法:

#include <ctime>#include <cstdlib>#include <iostream>using namespace std;int counter1[6] = { 0 };int counter2[6] = { 0 };int counter3[7] = { 0 };void show(){    cout << "******* counter1 *******" << endl;    double total = 0.0;    for (int i = 0; i < 6; ++i) {        total += counter1[i];    }    for (int i = 0; i < 6; ++i) {        cout << "  " << (i + 1) << ": " << (counter1[i] / total) << endl;    }    cout << "******* counter2 *******" << endl;    total = 0.0;    for (int i = 0; i < 6; ++i) {        total += counter2[i];    }    for (int i = 0; i < 6; ++i) {        cout << "  " << (i + 1) << ": " << (counter2[i] / total) << endl;    }    cout << "******* counter3 *******" << endl;    total = 0.0;    for (int i = 0; i < 7; ++i) {        total += counter3[i];    }    for (int i = 0; i < 7; ++i) {        cout << "  " << (i + 1) << ": " << (counter3[i] / total) << endl;    }}int random(){    static int max = RAND_MAX / 6 * 6;    int i = 0;    while (0 == i || i > max) {        i = rand();    }    return (i % 6 + 1);}void test(int times){    for (int i = 0; i < times; ++i) {        for (int j = 0; j < 7; ++j) {            int r1 = random();            int r2 = random();            ++counter1[r1 % 6];            ++counter1[r2 % 6];            if (!(6 == r1 && 6 == r2)) {                ++counter2[r1 % 6];                ++counter2[r2 % 6];                ++counter3[(6 * r1 - 6 + r2) % 7];            }        }    }    show();}int main(){    srand(time(NULL));    test(100000000);    return 0;}

其中random()可以均匀的取得[1, 6], 利用8楼方案扔100000000*7次后, 得到结果如下:

******* counter1 *******
  1: 0.16667
  2: 0.166665
  3: 0.166668
  4: 0.166664
  5: 0.166663
  6: 0.16667
******* counter2 *******
  1: 0.142858
  2: 0.171428
  3: 0.17143
  4: 0.171427
  5: 0.171425
  6: 0.171433
******* counter3 *******
  1: 0.14284
  2: 0.142871
  3: 0.142837
  4: 0.142883
  5: 0.142866
  6: 0.14285
  7: 0.142853

其中counter1表明扔骰子得到[1, 6](其实是[6, 1, 2, 3, 4, 5])的概率(其实是频率), 从结果可以看出前四位小数都是相同的, 可知random()的做法是正确的

其中counter2记录的是去掉x=6, y=6这种情况后, 得到[1, 6](其实是[6, 1, 2, 3, 4, 5])的概率(频率), 可以看出得到1少很多, 其实1是骰子的第6面, 得到这样的结果是因为x=6, y=6被去除而少统计了第6面的频数

其中counter3记录的是表达式取[1, 7](其实是[7, 1, 2, 3, 4, 5, 6])的概率(频率), 得到的结果的前四位小数也都是相同的, 说明8楼的方案从结果上看是对的

再回到我的疑惑, 我的疑惑无非是感觉[2, 3]号小孩似乎吃亏了, "凭什么, 第一次扔得6时, 我们俩(2, 3)注定没戏了, 而第一次扔得不是6, 只有一个家伙注定没戏?", 确定第一次扔得不是6时, 会有一个家伙注定没戏, 但第一次扔得6后, 初看(2, 3)两个似乎是没戏了, 但其实他们还有一次重生的机会, 此时第二次也扔得6

其实上面(本人的)各想法只是主观臆断, 就像空袭时, 士兵会跳入前一炸出的炕一样, 毫无科学根据, 但我们喜欢跟着感觉走

冷静下来, 分析下8楼的方案, 其实很快可以得到证明:

第1个小孩得到苹果的情况为:

(x, y) = { (2, 1), (3, 2), (4, 3), (5, 4) } + { (6, 5) } + { Part(6, 6) };

p(1) = 4 * (1/6) * (1/6) + (1/6) * (1/6) + (这一次不算, 重来后的某一次得到)

第{4, 5, 6, 7}个小孩与第1个小孩同样可得到这个概率

下面分析第2个小孩得到苹果的情况:

(x, y) = { (1, 1), (2, 2), (3, 3), (4, 4), (5, 5) } + { Part(6, 6) };

p(2) = 5 * (1/6) * (1/6) + (这一次不算, 重来后的某一次得到)

第3个小孩与第2个小孩将得到相同的概率

综上, 只要在(x, y) = (6, 6)时, 七个小孩得到苹果的概率相同时, 那么p(i)对于1-7的值就是相同的

令p1 = (5 / 36), 利用p1代入表达式(p1 + (1 - 7 * p1) * p1), 将表达式结果赋给p1再代入表达式计算...最后的结果就是p(i)的值为(1/7), 这是个求级限的问题(怎么求忘了)

综上, 8楼的答案是对的

原创粉丝点击