最近在一场 cf div2中有一个题用到long long
的随机数。学习了一下相关知识在此记录。
<cstdlib>
中的rand()
和srand()
函数是 语言使用的随机数生成方法,通过线性同余法计算。然后根据宏定义,产生的随机数最大范围是INT_MAX
,因此对于一些需要更大的随机数的情况就不适用了。且用这种方式生成不能保证序列的质量。
srand
常用时间作为种子:
#include <cstdlib>
#include <ctime>
using namespace std;
int main(){
srand(time(nullptr)); // 用当前时间作为种子
int min = 5, max = 10;
int randomValue = (rand() % (max - min)) + min;//范围[min,max)
randomValue = (rand() % (max - min + 1)) + min;//范围[min,max]
randomValue = (rand() % (max - min)) + min + 1;//范围(min,max]
}
所以,C++标准建议使用<random>
代替它们。
<random>(since C++11)
<random>中定义了随机数生成引擎、随机数分布律、不确定随机数和预定义的最佳算法实践。
可以预先定义随机数分布的概率分布,如正态分布 uniform_int_distribution、伯努利分布binomial_distribution、泊松分布 poisson_distribution 等等。
这里就不谈论原理了,只说一下怎么使用~
DEMO:
#include <random>
using namespace std;
int main(){
int min = 0,max = 100;
random_device seed; //硬件生成随机数种子
mt19937_64 rnd(seed()); //利用种子生成随机数引擎
uniform_int_distribution<> dist(min, max); //设置随机数范围,并为均匀分布
int random = rnd(engine); //生成一个随机数
}
题目:
https://codeforces.com/contest/1802/problem/C
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 210;
int g[N][N];
unordered_set<LL> us;
int n, m;
void solve(){
scanf("%d%d", &n, &m);
random_device seed; //硬件生成随机数种子
mt19937_64 rnd(seed()); //随机数引擎
uniform_int_distribution<LL> dist(0, LLONG_MAX); //设置随机数范围,正态分布
//随机化确定矩阵的第一行和第一列
for(int j = 1; j <= m; j++) g[1][j] = rand() % LLONG_MAX;
for(int i = 1; i <= n; i++) g[i][1] = rand() % LLONG_MAX;
while(1){
us.clear();
LL v = dist(rnd); //随机化确定一个2*2矩阵的值
for(int i = 2; i <= n; i++){
for(int j = 2; j <= m; j++){
LL t = g[i - 1][j - 1] ^ g[i - 1][j] ^ g[i][j - 1];
g[i][j] = t ^ v;
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
us.insert(g[i][j]);
if(us.size() == n * m){
break;
}
}
printf("%d\n", n * m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
printf("%lld%c", g[i][j], " \n"[j == m]);
}
int main(){
int T = 1;
scanf("%d", &T);
while(T -- ){
solve();
}
return 0;
}