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

46 篇文章 0 订阅
在没看8楼前, 我也想了个方案:

取七个骰子, 第一个骰子标号1-6, 第二个7-12, ..., 第六个标号31-36, 第七个标号37-42, 一起扔, 就会得到(1, 42)中的七个值, 这42个值对7取余后加1的结果有7种情况1-7, 且取[1, 7]都有5种情况, 也就是说, 这七个骰子一起扔后, 得到的点数对7取余加1后理论上应该均匀的得到[1, 7], 下面考虑这些经过计算处理的值

在特殊情况: i的个数比别的值j(j为集合{ 1, 2, 3, 4, 5, 6, 7 } - { i }中任何一个值) 的个数都多时, i为[1, 7]的概率是不是一样的, 我敢担保你证明不到不一样

方案在不满足上面的特殊情况时, 重来

不废话, 上检验代码:

#include <ctime>
#include <cstdlib>
#include <iostream>
using namespace std;

int counter1[6] = { 0 };
int counter2[7] = { 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 < 7; ++i) {
        total += counter2[i];
    }

    for (int i = 0; i < 7; ++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) {
        int counter[7] = { 0 };
        for (int j = 0; j < 7; ++j) {
            int r = random();
            int n = (6 * j + r) % 7;
            ++counter1[r % 6];
            ++counter2[n];
            ++counter[n];
        }

        int first_max_index = 0;
        int second_max_index = 0;
        for (int j = 1; j < 7; ++j) {
            if (counter[j] > counter[first_max_index]) {
                first_max_index = j;
            }
            else if (counter[j] == counter[first_max_index]) {
                second_max_index = j;
            }
        }

        if (first_max_index == second_max_index || counter[first_max_index] > counter[second_max_index]) {
            ++counter3[first_max_index];
        }
    }

    show();
}

int main()
{
    srand(time(NULL));
    test(100000000);
    return 0;
}


同样取100000000*7次, 得到结果如下:

******* counter1 *******
  1: 0.166677
  2: 0.166655
  3: 0.166652
  4: 0.166674
  5: 0.166671
  6: 0.166672
******* counter2 *******
  1: 0.14286
  2: 0.142889
  3: 0.142874
  4: 0.142852
  5: 0.142819
  6: 0.142858
  7: 0.142848
******* counter3 *******
  1: 0.142901
  2: 0.143036
  3: 0.142866
  4: 0.142786
  5: 0.142795
  6: 0.14283
  7: 0.142785
其中counter1是骰子得到[1, 6]的频率, counter2是骰子修改标号后经过计算处理得到[1, 7]的频率, counter3是"七个一起扔时出现某个值的次数大于出现别的值的次数"的频率

可以看出这个方案也是可行的(最大减最小:p(2) - p(7) = 0.143036 - 0.142785 = 0.000251), 至于为什么相比之下精确度低了, 我想原因应该是出现本方案中那种特殊情况的总次数相比8楼说的"不"出现x=6, y=6的情况的总次数少一些造成的, 就像我们用random()只测6次, 我们无法预料会出现多糟糕的结果一样, 总之是取样的困难度造成的精确度不及8楼的高, 当然复杂度也比8楼的高, 虽然本方案不能算一种好方法, 但我还是认为它是一种可行的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值