OSDN Git Service

:dove: Add plan: problemsetting
authorouuan <y___o___u@126.com>
Thu, 5 Sep 2019 06:25:10 +0000 (14:25 +0800)
committerouuan <y___o___u@126.com>
Thu, 5 Sep 2019 06:25:10 +0000 (14:25 +0800)
docs/intro/polygon.md [new file with mode: 0644]
docs/misc/gen-tests.md [new file with mode: 0644]
docs/misc/random.md
docs/topic/problemsetting.md [new file with mode: 0644]
mkdocs.yml

diff --git a/docs/intro/polygon.md b/docs/intro/polygon.md
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/docs/misc/gen-tests.md b/docs/misc/gen-tests.md
new file mode 100644 (file)
index 0000000..ceabc16
--- /dev/null
@@ -0,0 +1,129 @@
+数据生成是出题过程中必要的一步,也是对拍时所必需的,掌握一些生成数据的技巧,就能使造数据的过程更加轻松,造出来的数据强度更高。
+
+## 生成随机数据
+
+### 生成随机数
+
+请参考 [随机函数](./random.md) 页面。
+
+需要特别提醒的是,在生成值域比随机函数返回值更大的数时,请 **不要** 使用 `rand() * rand()` 之类的写法,这样的写法生成的随机数非常不均匀。
+
+另外,出题时推荐使用 [testlib](../intro/testlib/generator.md) 来造数据,可以保证在不同平台上同一个种子生成的随机数相同,并且种子会依据命令行参数自动生成。
+
+### 生成随机排列
+
+可以使用 STL 中的 `random_shuffle` 函数,也可以手写:
+
+```cpp
+for (int i = 1; i <= n; ++i)
+{
+    p[i] = i;
+    std::swap(p[i], p[rand() % i + 1]);
+}
+```
+
+### 生成随机区间
+
+常见错误方法:在 $[1,n]$ 中随机生成左端点 $l$,再在 $[l, n]$ 中随机生成右端点 $r$。这样的话生成的区间会比较靠右。
+
+较为正确的方法(推荐做法):在 $[1, n]$ 中随机生成两个数,取较小的作为左端点,较大的作为右端点。
+
+真正均匀随机的方法:在 $[1, n(n+1)]$ 中生成一个随机数 $x$,若 $x\le n-1$,再在 $[1, n]$ 中生成一个随机数 $y$,区间为 $[y,y]$;否则按“较为正确的方法”生成。
+
+### 生成随机树
+
+常用方法是为 $2\sim n$ 的每个节点 $i$ 从 $[1,i-1]$ 中随机选择一个父亲。这样做的话生成的树不是均匀随机的,期望高度为 $O(\log n)$。
+
+还有一种随机方法:从 $[i\cdot low, i\cdot high]$ 中随机选择 $i$ 的父亲。若 $low$ 和 $high$ 设置得当,可以造出强度较高的树。
+
+真正均匀随机的方法是利用 [Prufer 序列](../graph/prufer.md),先生成一个随机 Prufer 序列,再通过序列生成树。这样做的话,树的期望高度为 $O(\sqrt n)$。
+
+除此之外,可以随机一个排列来给节点重编号 / 打乱边的顺序。
+
+## 构造数据
+
+### 数据覆盖广度
+
+数据应当包含各个参数的最小值和最大值。
+
+数据应当包含各种边角情况。
+
+数据(包括输入、输出)最好覆盖到值域中的各个范围。
+
+### 防止特判
+
+为了防止特判过掉,可以将不同的构造结合在一个测试点中,或者数据的大部分是构造,掺杂小部分的随机。
+
+### 区间相关的题目
+
+常用构造:长度特别小(特殊地,全部为单点)、长度特别大(特殊地,全部为整个序列)。
+
+### 需要分解因数的题目
+
+可重质因数个数尽量多:$2$ 的幂。
+
+去重后质因数个数尽量多:最小的若干个质数相乘。
+
+约数尽量多:http://oeis.org/A002182 。
+
+### 树上问题
+
+常用构造:
+
+- 链
+- 菊花
+- 完全二叉树
+- 将完全二叉树的每个节点替换为一条长为 $\sqrt n$ 的链
+- 菊花上挂一条链
+- 链上挂一些单点
+- 一棵高度为 $d$ 且 $d>1$ 的树的根节点有两个儿子,左子树是一条长为 $d-1$ 的链,右子树是一棵高度为 $d-1$ 的这样的树。
+
+如果不是在考场上,还可以使用 [Tree-Generator](https://github.com/ouuan/Tree-Generator) 来生成各种各样的树。
+
+## 批量生成数据
+
+笔者推荐使用命令行参数 + bat / sh 的方法。
+
+例如:
+
+`gen.cpp`
+
+```cpp
+#include "testlib.h"
+
+using namespace std;
+
+int n, m, k;
+vector<int> p;
+
+int main(int argc, char* argv[])
+{
+    registerGen(argc, argv, 1);
+
+    int i;
+
+    n = atoi(argv[1]);
+    m = atoi(argv[2]);
+    k = rnd.next(1, n);
+
+    for (i = 1; i <= n; ++i) p.push_back(i);
+    shuffle(p.begin(), p.end()); // testlib.h 自带的 random_shuffle,使用 rnd.next() 进行 shuffle
+
+    printf("%d %d %d\n", n, m, k);
+    for (i = 0; i < n; ++i) printf("%d%c", p[i], " \n"[i == n - 1]); // 把字符串当作数组用,中间空格,末尾换行,是一个造数据时常用的技巧
+
+    return 0;
+}
+```
+
+`gen_scripts.bat`
+
+```text
+gen 10 10 > 1.in
+gen 1 1 > 2.in
+gen 100 200 > 3.in
+gen 2000 1000 > 4.in
+gen 100000 100000 > 5.in
+```
+
+这样做的好处是,对于不同的数据只需要写一个 generator,并且可以方便地修改某个测试点的参数。
\ No newline at end of file
index 3e4aa17..7c596c0 100644 (file)
@@ -55,7 +55,8 @@ int main() {
 
 内部使用的随机数生成器默认为 `rand()` 。当然也可以传入自定义的随机数生成器。
 
-!!! warning `random_shuffle` 已于 C++14 标准中被弃用,于 C++17 标准中被移除。
+!!! warning
+    `random_shuffle` 已于 C++14 标准中被弃用,于 C++17 标准中被移除。
 
 ### shuffle
 
diff --git a/docs/topic/problemsetting.md b/docs/topic/problemsetting.md
new file mode 100644 (file)
index 0000000..e69de29
index d050546..b25b774 100644 (file)
@@ -46,6 +46,7 @@ nav:
         - Validator: intro/testlib/validator.md
         - Interactor: intro/testlib/interactor.md
         - Checker: intro/testlib/checker.md
+      - Polygon: intro/polygon.md
       - OJ 工具: intro/oj-tool.md
       - LaTeX 入门: intro/latex.md
     - Docker 部署: intro/docker-deploy.md
@@ -360,8 +361,10 @@ nav:
     - 格雷码: misc/gray-code.md
     - 表达式求值: misc/expression.md
     - 在一台机器上规划任务: misc/job-order.md
+    - 生成测试数据: misc/gen-tests.md
   - 专题:
     - RMQ: topic/rmq.md
+    - 出题: topic/problemsetting.md
 
 # Theme
 theme: