晓轩

博客园 首页 联系 订阅 管理

给定能随机生成1到5的函数,写出能随机生成1到7的函数

算法实现:拒绝采样法,生成目标范围的随机数,即生成满足题目要求的样本空间,5<7<5*5,只需两次调用rand_5(),可产生25个样本空间分别和1--25个正整数一一映射,为了保证等概率,22,23,24,25舍去;如图所示:1--7中的每个数在样本空间出现的概率为3/25, 所以它们等概率出现的概率就为1/7了,如图所示,算法实现如下:

     1   2   3     5

1   1   2   3   4   5

2   6   7   1   2   3

  4   5   6   7   1

4   2   3   4   5   6

  7   *   *   *   *

 代码如下:

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

int rand_5()
{
 return rand()%5+1;
}

int rand_7()
{
 int row,col,idx;
 do
 {
  row=rand_5();
  col=rand_5();
  idx=col+(row-1)*5;
 }while(idx>21);
 return   1+(idx-1)%7;
}

int main()
{
 int T;
 srand((unsigned)time(NULL));
 cin>>T;
 while(T--)
 {
  cout<<rand_7()<<endl;
 }
 return 0;
}

发散一下 :给定能随机生成1到5的函数rand_5(),随机生成1到1000的函数rand_1000(),显然5^4=625<1000<5^5=3125, 可以5次调用rand_5(),生成1--3125个正整数,取1--3000,将3001--3125舍去;可保证1--1000每个数出现的概率为1/1000.
      更一般的:给定能随机生成1到m的函数rand_m(),随机生成1到n的函数rand_n(), 其中(m<n) .
             算法实现:1...求正整数k,使 m^(k-1)<n<=m^k;
                               2... k次调用rand_m(),输出k位m进制数N;
                               3...if(1<=N<=n*(m^k/n))   return   1+(N-1)%n; ...else   重新执行2...    

代码如下:
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;

//产生1-m的随机数
int rand_m(int m)
{
 return rand()%m+1;
}

//确定k值
int BitNum(int n,int m)
{
 int k=0,p=1;
 while(p<n)
 {
  ++k;
  p*=m;
 }
 return k;
}

//产生1-n的随机数
int rand_n(int n,int m)
{
 int N,cnt,s=1,i;
 cnt=BitNum(n,m);
//求m^k
 for(i=1;i<=cnt;i++)
  s*=m;
 while(true)
 {
  N=0;
  for(i=1;i<=cnt;i++)
  {
   N=N*m+rand_m(m)-1;
  }
  N=N+1;
  if(N>=1&&N<=n*(s/n))
   return 1+(N-1)%n;
  else  continue;
 }
}

int main()
{
 int T,n,m,i;
 srand((unsigned)time(NULL));
 cin>>T;
 while(T--)
 {
  cin>>n>>m;
  for(i=1;i<=10;i++)
   cout<<rand_n(n,m)<<" ";
  cout<<endl;
 }
 return 0;
}

posted on 2013-06-13 20:48  晓轩  阅读(465)  评论(0)    收藏  举报