算法导论 5.1-2

:描述random(a, b)过程的一种实现,它只调用random(0,1)。作为a和b的函数,你的程序期望运行时间是多少?

Randomab)需满足的条件:

1ab之间的元素是等概率出现的

2)其概率=1/(b-a+1)

以下解题思路仅实现了---等概率出现,至于得到的概率<=1/(b-a+1)

解析:1·Random(0,1)可以等概率产生01,如果将(b-a+1)写成二进制形式,则可以用Random(0,1)产生的值(01)串起来表示(b-a+1),执行Random(0,1) p次后,得到的结果将是Random(0, 2^p),当2^p >= (b-a+1)时,实际上0~(b-a+1)【准确的说是0~2^p】之间的元素已经可以等概率出现了

2·分治法:

2.1分解,将a-b区间分成2部分,通过random(0,1)控制,则进入前半部和后半部的概率是一样的;

2.2.递归的处理前后两个部分,若问题足够小,即落到某个具体位置上时,则直接返回;

注意:当元素个数(b-a+1)不是2的幂次时,直接进行分治得不到等概率

元素;此时需要添加(b+1)(b+2)(b+3)···以使得元素个数等于2的幂次,然后再对a~(b+i)进行分治

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <cstdlib>  
  3. #include <time.h>  
  4. using namespace std;  
  5.   
  6. int random(int a , int b)  
  7. {  
  8.     int p,m=1;               //m用来保存2^p  
  9.     for(p=0 ; m<b-a+1; p++) //p是二进制位数  ,b - a + 1 至少要p位二进制才能存下。
  10.     {  
  11.         m *= 2;              //再用m保存十进制的值  
  12.     }  
  13.   
  14.     m = rand()%2;  
  15.   
  16.     for(int i=0 ; i<p; i++)  
  17.     {  
  18.         m = m*2+rand()%2;//将生成的01串表示成十进制,注意每次都要左移,所以m*2  
  19.     }  
  20.   
  21.     if(m > b-a)  
  22.     {  
  23.         return random(a , b);  
  24.     }  
  25.     else  
  26.     {  
  27.         return m+a;  
  28.     }  
  29. }  
  30. int main()  
  31. {  
  32.     int a,b;  
  33.     cin >> a >>b;//输入3和7  
  34.     srand(time (0) );  
  35.     int m;  
  36.     int three , four , five ,  
  37.         six , seven;//这几个变量用来统计3,4,5,6,7出现次数  
  38.     three = four = five =  
  39.         six = seven=0;  
  40.     for(int i=0 ; i<1000 ; i++)  
  41.     {  
  42.         m = random(a , b);  
  43.         cout << m << endl;  
  44.         switch(m)  
  45.         {  
  46.             case 3:  
  47.             three++;break;  
  48.             case 4:  
  49.             four++;break;  
  50.             case 5:  
  51.             five++;break;  
  52.             case 6:  
  53.             six++;break;  
  54.             case 7:  
  55.             seven++;  
  56.             default:break;  
  57.         }  
  58.     }  
  59.     cout << three << ' ' << four  
  60.     << ' ' << five << ' ' << six << ' ' <<seven;  
  61.   
  62.     return 0;  
  63. }  
:已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10
(参考答案:这题主要考的是对概率的理解。程序关键是要算出rand10,1到10,十个数字出现的考虑都为10%.根据排列组合,连续算两次rand7出现的组合数是7*7=49,这49种组合每一种出现考虑是相同的。怎么从49平均概率的转换为1到10呢?方法是:
1.rand7执行两次,出来的数为a1.a2.

2.如果a1*7+a2<40,b=(a1*7+a2)/10+1,如果a1*7*a2>=40,重复第一步)。参考代码如下所示

[cpp]  view plain copy
  1. nt rand7()    
  2. {    
  3.   return rand()%7+1;    
  4. }    
  5.     
  6. int rand10()    
  7. {    
  8.   int a71,a72,a10;    
  9.   do     
  10.   {    
  11.     a71= rand7()-1;    
  12.     a72 = rand7();    
  13.     a10 = a71 *7 + a72;    
  14.   } while (a10>= 40);    
  15.   return (a71*7+a72)%10+1;  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值