筆記 | 如何正確地生成一個隨機數


在最近的一場CF的題解中,提到了這篇blog:Don't use rand(): a guide to random number generators in C++

大概概述一下這篇神仙blog說了啥:

  • CF評測機上(以及我們會遭遇的許多windows評測機上)RAND_MAX很小,只有32767
  • 不幸的是,random_shuffle用的也是這個自帶的rand(),元素在數組里移動的距離也很小。
  • rand()使用的偽隨機算法是 linear congruential generator (線性同余發生器),在低位循環節很低。

那么如何正確地生成一個隨機數呢?神仙blog提供了這樣一個東西: 庫里的mt19937。

這個奇葩的名字來自於它使用的算法——Mersenne Twister算法,以及它用到的質數——\(2^{19937} - 1\)

怎么用呢?

mt19937 rng(seed);
printf("%u\n", rng());

上面那句相當於srand(seed),然后調用你定義的rng()可以獲得一個unsigned int類型的隨機數。

如果你要生成unsigned long long 類型的話,使用mt19937_64即可。

那么怎么替代random_shuffle()呢?使用shuffle()函數,把你的mt19937傳進去,像這樣:

shuffle(a, a + n, rng);

這樣就能讓數組內的元素移動足夠大的距離——讓shuffle更隨機了。

附:完整生成隨機數代碼

#include <cstdio>
#include <chrono>
#include <random>
using namespace std;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int main(){
    printf("%u\n", rng());
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM