蓝桥杯-古代赌局问题

松鼠的窝 2018-03-21

问题描述:

俗话说:十赌九输。因为大多数赌局的背后都藏有阴谋。
不过也不尽然,有些赌局背后藏有的是:“阳谋”。

有一种赌局是这样的:桌子上放六个匣子,编号是1至6。
多位参与者(以下称玩家)可以把任意数量的钱押在某个编号的匣子上。
所有玩家都下注后,庄家同时掷出3个骰子(骰子上的数字都是1至6)。
输赢规则如下:

1.若只有1个骰子上的数字与玩家所押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目赔付(即1比1的赔率)。
2.若2个骰子上的数字与玩家所押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目的2倍赔付(即1比2的赔率)。
3.若3个骰子上的数字都与玩家押注的匣子号相同,则玩家拿回自己的押注,庄家按他押注的数目的10倍赔付(即1比10的赔率)。

乍一看起来,好像规则对玩家有利,庄家吃亏。但经过大量实战,会发现局面很难说,于是怀疑是否庄家做了手脚,庄家则十分爽快地说:可以由玩家提供骰子,甚至也可以由玩家来投掷骰子。

你的任务是:通过编程模拟该过程。模拟50万次,假定只有1个玩家,他每次的押注都是1元钱,其押注的匣子号是随机的。再假定庄家有足够的资金用于赔付。最后计算出庄家的盈率(庄家盈利金额/押注总金额)。

问题分析:

此题是一道简单的概率题,在蓝桥杯比赛中这种题属于送分,但对于初次接触此题的同学来说,仍有一些要注意的地方,比如说求这个1-6的随机数,C++与C是不一样的函数,这两个函数的原理也不一样。

C++中rand()函数,是返回0-RAND_MAX之间均匀分布的伪随机整数。 RAND_MAX必须至少为32767。rand()函数不接受参数,默认以1为种子(即起始值)。

C中random()函数,功能:随机数发生器 用法:intrandom(intnum); 根据提供的num,随机产生0-num-1范围的数据。

产生一定范围随机数的通用表示公式

1)要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
2)要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
3)要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
4)通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
5)要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。
6)要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。

代码描述:

1 #include<iostream>
 2 #include<cstdlib>//一定要加c这个字母,不要把C语言的头文件与C++中的弄混淆了 
 3 using namespace std;
 4 int f();
 5 double moni(int n);
 6 int main(){
 7     int n=500*1000;//定义50万,亮点 
 8     cout<<moni(n)/n;
 9     return 0;
10 } 
11 int f(){
12     int a,b,c,p,i=0;
13     /*模拟3次骰子,注意求小数的随机数与求1-10整数的随机数,使用int将其强制转换为整型*/
14     a=(int)(rand()/(RAND_MAX+0.0)*6)+1;//RAND_MAX
15     b=(int)(rand()/(RAND_MAX+0.0)*6)+1;
16     c=(int)(rand()/(RAND_MAX+0.0)*6)+1;
17     /*模拟此人此次押注*/ 
18     p=(int)rand()/(RAND_MAX+0.0)*6+1;
19     //下面统计压中次数是一个亮点 
20     if(a==p) i++;
21     if(b==p) i++;
22     if(c==p) i++;
23     if(i==3) return -10;
24     if(i==2) return -2;
25     if(i==1) return -1;
26     return 1;
27 }
28 double moni(int n){
29     double sum=0;
30     for(int i=0;i<n;i++)//模拟n次 
31     sum+=f();
32     return sum;
33 }