笔记 | 如何正确地生成一个随机数


在最近的一场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