mt19937的使用

· · 个人记录

网上讲的都不是很清楚,啃了一下CF上的Don't use rand()还有网上杂七杂八的博客,大概归纳一下它的用法

mt19937产生的随机数值域大,周期长,耗时短(约是rand()\frac 13),所以是完全吊打rand()的存在

定义

首先,定义mt19937的头文件为#include<random>,同时也被包括在了万能头里面

然后我们可以这样写:

mt19937 a;

你发现他长得很像一个定义类型的形式,可以理解为我定义了一个变量名为amt19937类型的变量。

你还可以这样写:

mt19937 a(114514);

其中括号内为随机种子。

直接使用

那么我们定义出来以后怎么用呢:

直接

cout<<a()<<"\n";

这里a又长得像一个函数,可以直接输出以114514为随机种子的随机值了。

顺带一提,它的值域为 [0,2^{32}-1],即unsigned int的存储范围。

随机序列

这只是它最简单的应用,单有这个还不能取代 random_shuffle 这些东西。

于是我们还可以这样写(假设 b 是一个序列,长度为 n

shuffle(b+1,b+1+n,a);

注意shuffle位于#include<algorithm>库中

就可以对b进行一个随机打乱的操作,第三个参数为一个mt19937变量(暂且这么称呼它),表示你随机打乱所用的随机数生成器

再注意一下你在进行操作之后a会变化,意思是说你对两个一样的数组 b,c 执行下列操作得到的序列不同

shuffle(b+1,b+1+n,a);
shuffle(c+1,c+1+n,a);

具体地,你可以参考下列代码:

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<random>
using namespace std;
int b[15],c[15];
mt19937 a;
int main()
{
    int n=10;
    for(int i=1;i<=n;i++)b[i]=c[i]=i;
    shuffle(b+1,b+1+n,a);
    shuffle(c+1,c+1+n,a);
    for(int i=1;i<=n;i++)cout<<b[i]<<" ";cout<<"\n";
    for(int i=1;i<=n;i++)cout<<c[i]<<" ";cout<<'\n';
}

产生范围内的随机数

我们当然可以用mt19937后再取模,但是概率其实多半不均等。

这个我们需要用到另一个东西:

uniform_int_distribution

它也存在于random库中。

我们定义类似于mt19937,也可以理解为定义了一个函数。

uniform_int_distribution<>a(114,514)

这里的尖括号不能省,圆括号框定了a产生随机数的范围。

然后使用的话我们也是类似函数,但是要传一个参数,为一个mt19937变量

然后就可以随机产生范围的数了

其他