继续昨天的问题,回顾一下相应的规则。
1. 同学按座位号依次进行抽签;
2. 抽签过程中抽到的同学不能为之前已经抽到的同学;
3. 按照昨天的规则,为了计算简便,可以抽到自己。
那么根据昨天的分析,我们得到的抽签次数的理论平均值为
由于该问题的分析过于复杂,另外昨天解决该问题的时间也比较仓促,所以我们的分析和计算可能出现问题。那么我们可以借助一下计算机来模拟仿真一下这个问题。
其算法如下:
1. 设置了被抽奖人序号和每个同学抽奖次数的统计向量(分别为向量a和向量b),每个向量均是n维的,n是抽奖人数,并且每个向量初始值全部是0;
2. 设置一个n次的循环。在循环内部,当第k位同学在抽签时,先设置一个从1到n的随机数。如果这个随机数在向量a中出现过,那么继续制造一个从1到n的随机数,然后将向量b中第k位的数字加上1,表示进行了一次抽签的意思;如果这个随机数在向量a中未出现过,则将向量b中第k位的数字加上1后,进入第k+1次的循环;
3. (2)中的过程一共进行k次;
4. 然后把向量b中的所有结果进行加和,得到本轮抽签的总次数;
5. 为了能得到一个更准确的单轮抽签次数的平均值,设置一个轮次数计算一下平均值即可。
MATLAB程序如下:
function y=party1(n)
nn=linspace(0,0,n); %%被抽奖人,向量a
con=linspace(0,0,n); %%抽奖次数计数,向量b
for i=1:n
kk=ceil(rand()*n); %%被抽号码
for k=1:1000*n
if ismember(kk,nn)==1 %%继续抽,是否有之前的元素
kk=ceil(rand()*n);
con(i)=con(i)+1;
else break
end
end
nn(i)=kk;
con(i)=con(i)+1;
end
y=sum(con);
上面是单轮抽签次数的模拟情况。下面是模拟轮数的情况。
function y=partycon1(m,n) %%m为轮次数,n为每轮多少人
mm=linspace(0,0,m);
for i=1:m
mm(i)=party(n);
end
y=mm;
在运行界面只需输入下面两行即可
>>partycon1(100,40)
>>mean(ans(:))
第一行是进行100轮的模拟,第二行是取这100轮平均值。
根据我们的理论计算,40人进行抽签的抽签平均次数约为171.14次,而我们的模拟计算结果如下表所示。
轮次 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 平均 |
结果 | 170.41 | 166.34 | 179.12 | 165.97 | 169.34 | 170.79 | 174.30 | 167.36 | 175.94 | 171.06 |
注意,每轮测试100次,经过900轮测试,其平均抽签次数为171.06,与理论计算结果差距微小,应该说我们昨天分析的是正确的。
下面我们要对规则进行一定的修改,也就是我们定义不能抽到自己,并定义抽到自己视为本次抽签作废(不在总的抽签次数上加上1),然后我们先进行模拟,之后再进行理论分析。其模拟结果如下表:
轮次 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 平均 |
结果 | 169.51 | 172.63 | 161.41 | 178.30 | 175.04 | 169.73 | 176.60 | 160.79 | 168.76 | 170.31 |
我们看,这两个计算结果间的差距微小,甚至可以忽略不计,那么接下来我们需要从理论上解释一下其原因,请看下回分解。