几道有趣的概率题

这几天在刷题,遇到几道有趣的概率题,需要设计算法,编程实现,整理一下:

给定N张扑克牌和一个随机函数,设计一个洗牌算法

void fun(vector<int>& v)                                                                                                                                                                
{      
     srand(time(0));
     for (int n = v.size(); n > 0; n--)
     {  
         int index = rand() % n;
         swap(v[n-1], v[index]);
     }  
 }  

如何等概率地从n个数中随机抽出m个数?

//假设这n个数的序号依次为0,1,2,...,n-1,数组名为num
void knuth1(int* pNum, int m, int n)
{
    srand((unsigned int)time(0));
    for (int i=0; i<n; i++)
    {
        if (rand()%(n-i) < m) //rand()%(n-i)的取值范围是[0, n-i)
        {
            cout << pNum[i] << endl;
            m--;
        }
    }
}

或者维护一个set,每次取一个元素删除下次继续取,也是可以的,但是有一点不好,当set中元素很少时候,rand()函数可能要很久才产生这个数,效率不高。

如果n未知,可参考 从未知大小的n个数中取m个数,使各数被取出的概率相等


给定一个能够生成0,1两个数的等概率随机数生成器”,如何生成⼀个产生0,1,2,3的等概率随机数生成器?
和上题类似,如何用rand7生成rand9?


int rand0_3()
{
    return rand0_1()+rand0_1();
}

int rand9()
{
    int n=0;
    do{
        n=(rand()7-1)*7+rand()7;
    }while(n>45)
    return n%9+1;
}
//rand7 --》 rand5
int Rand5(){
    int x = ~(1<<31); // max int
    while(x > 5)
        x = Rand7();
    return x;
}

有一枚硬币,以p的概率产生正面,以1-p的概率产生背面,如何利用它产生个0.5概率的生成器?

制作 1 2 发生概率都是 1 / 2 的发生器,连续发生2次,则发生00,11的概率为p*p,(1-p)(1-p),发生10,01的概率都为p(1-p),在发生10时返回1,发生01时返回2,则发生12的概率相等

制作 1 2 3 发生概率都是 1 / 3的发生器,连续发生3次,则发生001,010,100的概率都为p*p*(1-P),或者是110,101,011概率都为p*(1-p)*(1-p),则用001,010,100分别对应1,2,3返回,即可使得发生1,2,3的概率都为1/3
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值