zoukankan      html  css  js  c++  java
  • 随机生成数

    如何用随机数生成0到n之间的m个不重复的数

    1、最直接的方法就是先随机生成一个0到n之间的数,判断这个数是否已被选上,如果以前没选过,则选上,如果以前已选,则丢弃

    1. void common(int n,int m)  
    2. {  
    3.     int * randnum=(int *)malloc(n*sizeof(int));  
    4.     memset(randnum,0,n*sizeof(int));   //把n个位置全部置0   
    5.     srand(time(NULL));  
    6.     while(m)  
    7.     {  
    8.         int cur=rand()%n;  
    9.         if (randnum[cur]==0)   //进行判断,如果当前数没有选择过,则选择并输出   
    10.         {  
    11.             cout<<cur<<endl;  
    12.             randnum[cur]=1;  
    13.             m--;  
    14.         }  
    15.     }  
    16.     free(randnum);  
    17.   
    18. }  

    这种方法简单易懂,但是需要额外的空间来确保取出的数不重复,那么我们有没有更为简单的方法呢,答案是肯定的

    2、先上代码,后做解释

    1. void mRand(int n ,int m)  
    2. {  
    3.   
    4.     srand(time(NULL));  
    5.     for (int i=0;i<n;i++)  
    6.     {     
    7.         if(rand()%(n-i)<m)  
    8.         {  
    9.             cout<<i<<endl;  
    10.             m--;  
    11.         }  
    12.           
    13.     }  
    14. }  

    上边的代码虽然简洁,但是不易懂,我们接下来说明一下

    首先是一个循环,这个循环确保了输出的数是不重复的,因为每次的i都不一样

    其次是m个数,在每次循环中都会用rand()%(n-i)<m来判断这个数是否小于m,如果符合条件则m减1,直到为0,说明已经取到m个数了

    再次是如何保证这m个数是等概率取到的

    在第一次循环中i=0, n-i=n, 则随机数生成的是0-n-1之间的随机数,那么此刻0被取到的概率为 m/n-1
    在第二次循环中i=1,n-i=n-1,则随机数生成的是0-n-2之间的随机数,这时1被取到的概率就和上一次循环中0有没有取到有关系了。假设在上一次循环中,没有取,则这次取到的1的概率为 m/n-2;假设上一次循环中,已经取到了,那么这次取到1的概率为m-1/n-2,所以总体上这次被取到的概率为 (1-m/n-1)*(m/n-2)+(m/n-1)*(m-1/n-2),最后通分合并之后的结果为m/n-1和第一次的概率一样的
    同理,在第i次循环中,i被取上的概率也为m/n-1

    所以这m个数是等概率取到的

    1. <PRE></PRE>  
    2. <PRE></PRE>  
    3. <PRE></PRE>  
    4. <PRE></PRE>  
  • 相关阅读:
    HDU 1010 Tempter of the Bone(DFS剪枝)
    HDU 1013 Digital Roots(九余数定理)
    HDU 2680 Choose the best route(反向建图最短路)
    HDU 1596 find the safest road(最短路)
    HDU 2072 单词数
    HDU 3790 最短路径问题 (dijkstra)
    HDU 1018 Big Number
    HDU 1042 N!
    NYOJ 117 求逆序数 (树状数组)
    20.QT文本文件读写
  • 原文地址:https://www.cnblogs.com/zswbky/p/5432120.html
Copyright © 2011-2022 走看看