幾道有趣的概率題

這幾天在刷題,遇到幾道有趣的概率題,需要設計算法,編程實現,整理一下:

給定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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章