不重复随机数列生成

本文介绍了一种使用C++实现生成k个不重复随机数的方法。通过创建一个大小为k的数组,利用随机下标选择未输出过的元素,并将其添加到结果数组中,以确保生成的数列不重复。

问题描述:

随机生成k个不重复的随机数(或生成0至k-1以随机顺序构成的数列)

算法:

rand不直接产生值,而是产生下标,下标可以重复,但要保证数组中都是不重复且没有输出过的数字


①一个大小为k的数组temp,temp[i]=i;一个随机下标的范围range,range初始为k;一个随机数组result

②随机生成0至range-1的一个下标index,将temp[index]放入result

③temp[index]=temp[range-1]

④range--,转②

代码:

#pragma once
#include<iostream>
#include<vector>
#include<time.h>
using namespace std;

//返回k个不同随机数按序组成的vector(以随机顺序返回0至k-1构成的vector
vector<int> diffRand(int k)
{
	vector<int> result(k);
	vector<int> flag(k);
	for (int i = 0; i < k; i++)
		flag[i] = i;
	int range = k;//随机下标的范围
	srand((unsigned int)time(0));
	for (int i = 0; i < k; i++)
	{
		int randIndex = rand() % range;
		result[i] = flag[randIndex];
		flag[randIndex] = flag[range - 1];
		range--;
	}
	return result;
}

void main()
{
	vector<int> result = diffRand(10);
	for (int i = 0; i < (int)result.size(); i++)
		cout << result[i] << ' ';
	cout << endl;
	system("pause");
}


### 原理 线性同余法是一种生成伪随机数的方法,其核心原理是将当前的伪随机数值乘以一个常数 `A` 再加上另一个常数 `C`,然后将除以 `M` 得到的余数作为下一个伪随机数。其中,最近一次生成的伪随机数的值就是内部状态,伪随机数的种子被用来对内部状态进行初始化。线性同余法生成的随机数列要满足一些准则,如函数应是完整周期的产生函数,即在重复之前产生出 0 到 `M` 之间的所有数;产生的序列应看起来是随机的;函数应该用 32bit 算术高效实现 [^1][^3]。 ### 实现方法 线性同余法的公式为:$X_{i + 1}=(A\times X_{i}+C)\bmod M$,其中 $X_{i}$ 是当前的伪随机数,$X_{i + 1}$ 是下一个伪随机数,$A$ 是乘数,$C$ 是增量,$M$ 是模数,初始的 $X_{0}$ 是种子。 在实现时,要注意一些参数的选择。`M` 的作用是产生 0 到 `M - 1` 之间的伪随机数,其大小直接影响伪随机数序列的周期长短,所以 `M` 应尽可能取比较大的值;`A` 和 `C` 的值越大,产生的伪随机数越均匀,若 `A` 和 `M` 互质,产生随机数的效果更好。同时,在编程实现时要防止因 `A`、`C` 取值太大造成结果溢出。以下是一个用 C 语言实现线性同余法生成随机数列的示例代码: ```c #include <stdio.h> #include <stdlib.h> int main() { int n, i, A, b, m, s; scanf("%d %d %d %d %d", &n, &s, &A, &b, &m); int *a = (int *)malloc(sizeof(int) * (n + 1)); a[0] = s; for (i = 0; i < n; i++) { a[i + 1] = (a[i] * A + b) % m; printf("%d ", a[i + 1]); } return 0; } ``` ### 应用 线性同余法由于速度快,在一些对随机数质量要求是极高的场景中应用广泛。例如在计算机模拟领域,如蒙特卡罗模拟,需要大量的随机数来模拟各种可能的情况;在游戏开发中,用于生成随机的地图、敌人的出现位置等;在密码学的一些简单场景中,可用于生成初始的密钥或随机数序列 [^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值