如何科学地对拍
对拍
windows:
@echo off
:loop
gen
friend
brute
fc friend.out friend.ans
pause
if %errorlevel%==0 goto loop
pause
文件名为friend(.exe/.in/.out)
ubuntu:
#!/bin/bash
while true; do
./gen > tst.in
./my < tst.in > my.out
./std < tst.in > std.out
if diff my.out std.out -b ; then
printf "AC\n"
else
printf "WA\n"
exit 0
fi
done
Windows中的随机变量(随机性较强): %RANDOM%
Ubuntu中: $RANDOM
可以传入数据生成器,作为随机种子。
如果想要出一套信息学竞赛模拟题, 或者要对拍以验证自己程序的正确性,数据生成器是必不可少的。
随机数
数据的随机性很重要。 只有足够随机的数据才可以均匀地覆盖到各种情况。
但是<cstdlib>
里的rand()
不是很好用:
- 它在不同平台上表现不同
- 它的线性递推算法随机性较弱。
在c++11
或以上的c++版本,可以使用更好的mt19937
随机化工具。
要: #include<random>
它基于梅森素数,周期非常长,随机性也有保证。 只是稍慢一点。
我们可以这样定义一个基于mt19937
的随机函数
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rng2(chrono::steady_clock::now().time_since_epoch().count());
rng
的作用和rand()
相同, 不过需要注意:
rng()
\(\in [0, 2^{32})\)rng2()
\(\in [0, 2^{64})\)
chrono::steady_clock::now().time_since_epoch().count()
表示当前时间。 它是随机种子。
当然也可以自定义随机种子:
rng.seed(种子)
限定范围的随机数
//这样来生成一个 1 ~ n 的随机数
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
#define ll long long
ll rd(ll x) {
return rng() % x + 1;
}
如何造和图论有关的数据?
生成一张随机的树的方法
for(int i = 2; i <= n; i++) {
int u = rd(i-1);
printf("%d %d\n", u, i); //(u, i) 为一条边的两个端点
}
生成一张随机联通图的方法
set<pair<int, int> > st;
for(int i = 2; i <= n; i++) {
int u = rd(i-1);
st.insert(make_pair(u, i));
}//先生成它的生成树
while(st.size() < m) {
int u = rd(n), v = rd(n);
if(u > v) swap(u, v);
pair<int, int> pii = make_pair(u, v);
if(u == v || st.find(pii) != st.end()) continue;
st.insert(pii);
}
//这张图无重边和自环