在\(OI\)学习过程中,数据是必不可少的。不管是在\(OJ\)上提交狂\(Wa\)不止时,还是考场上怀疑自己的算法但出题人给的数据又能正确\(AC\)时,数据都显得尤为重要。所以我特地写一篇随机数据生成的博客来总结一下。
随机函数
首先我们需要认识一下\(C++\)自带的随机函数\(rand()\)。头文件\(algorithm\)自带\(srand\)与\(rand\)两个函数。
使用\(rand()\)函数会随机返回一个范围在[0,RAND_MAX]之间的整数。RAND_MAX等于\(2147483647\)也就是\(int\)能保存的最大的正整数。你想要\(rand\)一个[0,n-1]范围的数你可以\(rand()\)%\(n\),如果你想要\(rand()\)出负数你可以写成\(rand()\)%(\(2\)*\(n\))-\(n\)。这样\(rand\)出的数都是在\([-n,n-1]\)中等概率取值的。如果你要随机实数就写成\((double)rand()/eps\)。令\(eps\)等于\(10\)的若干次方即可。\(srand()\)函数带的参数是随机种子,种子不一样随机出来的数也不一样。我一般习惯写成\(srand(time(0))\),那么就会以当前时间为种子。第一次随机取值会根据种子来决定,之后的随机取值会以上一次随机出的值为种子来随机。这就是随机函数的运行机制。另外,\(algorithm\)里的random_shuffle也是根据种子来随机的。
随机生成排列
for(int i=1;i<=n;i++)
a[i]=i;
random_shuffle(a+1,a+n+1);
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
随机生成若干个区间
for(int i=1;i<=m;i++) {
int l=rand()%n+1,r=rand()%n+1;
if(l>r)swap(l,r);
printf("%d %d\n",l,r);
}
随机生成树
下面的\(n\)全部代表点数,\(m\)全部代表边数。
for(int i=2;i<=n;i++) {
int i_father=rand()%(i-1)+1;
printf("%d %d\n",i_father,i);
}
生成链
for(int i=2;i<=n;i++)
printf("%d %d\n",i-1,i);
生成菊花图
for(int i=2;i<=n;i++)
printf("1 %d\n",i);
随机生成联通图
#include
不要求联通就不要先建一棵树了。