QOJ.ac

QOJ

時間限制: 2.0 s 記憶體限制: 1024 MB 總分: 100 可 Hack ✓

#17162. 缺失的数字

统计

给你一个由 $n$ 个介于 $1$ 到 $n+1$ 之间的整数组成的数组。数组中某些整数可能会出现多次。显然,在 $1$ 到 $n+1$ 的整数中,至少有一个整数在数组中缺失。你的任务是找到任意一个这样的缺失整数。通常情况下这很简单,但遗憾的是:你的计算机没有足够的内存来存储整个数组。

因此,你需要设计一个流式算法(streaming algorithm)。非正式地讲,数组的元素会逐个给出,你无法随机访问它们。不过,有一点可以安慰:在接收到数组的最后一个元素后,你可以重新从头开始读取它。理想情况下,你希望避免这种情况,并在一次扫描(one pass)中解决整个问题。然而,有时(包括本题)为了避免占用太多内存,对输入进行多次扫描可能是必要的。你需要平衡这两个方面,既不能使用太多内存,也不能对数组进行太多次扫描(如果允许你存储 $n$ 个比特的内存或进行 $n$ 次扫描,这个问题就变得平凡了)。

然而,还有一个难点。由于技术原因,你需要设计一个基于字符集 $\{0, 1, \dots, n + 1\}$ 的确定性有限状态自动机(DFA)来实现你的算法逻辑。字符集中的字符对应于你从流中读取时接收到的信息:$1$ 到 $n+1$ 的数字表示从数组中读取了相应的整数,而数字 $0$ 表示你已经到达了数组的末尾。在第 1 到第 7 次到达数组末尾后,数组将以与之前相同的顺序再次给出,且每次都以字符 $0$ 结尾表示数组结束。因此,你的 DFA 将总共被输入 8 次字符串 $a_1, a_2, \dots, a_n, 0$(这里 $a_1, a_2, \dots, a_n$ 是隐藏的数组)。最后,在执行的任何时刻,你的自动机都可以“宣布”它已经知道了该问题的某个正确答案;在这种情况下,执行将停止。如果你的 DFA 在完整读取该流(包括末尾的 $0$ 字符)8 次后仍未停止,则不被视为正确解。同样,如果它停止了,但给出了错误的答案,也不被视为正确解。

让我们正式地描述这个问题。存在一个由 $n$ 个介于 $1$ 到 $n+1$ 之间的整数组成的隐藏数组 $a_1, a_2, \dots, a_n$。在样例中 $n = 4$,在所有其他测试点中 $n = 250$。你需要指定一个最多包含 4000 个状态的有限状态机,状态编号从 $0$ 到 $q - 1$,其中 $q \le 4000$ 是状态数。对于状态 $i$($0 \le i \le q - 1$),你需要指定 $n + 2$ 个数字 $\delta(i, 0), \delta(i, 1), \dots, \delta(i, n + 1)$。数字 $\delta(i, j)$ 表示当 DFA 处于状态 $i$ 且从输入中读取数字 $j$ 时的行为。它必须是介于 $-(n + 1)$ 到 $q - 1$ 之间(含两端)的整数。负整数对应于执行停止并给出答案的情况;具体来说,$-s$ 对应于你的 DFA 宣布 $+s$ 是该问题的一个正确答案。非负整数对应于执行继续,且自动机的状态从 $i$ 转移到 $\delta(i, j)$。自动机的执行从状态 $0$ 开始。

如果你的 DFA 在读取字符串 $a_1, a_2, \dots, a_n, 0, a_1, a_2, \dots, a_n, 0, \dots, a_1, a_2, \dots, a_n, 0$(即数组重复 8 次)的过程中,在某个时刻停机并给出了正确的答案,则认为它在数组 $a_1, a_2, \dots, a_n$ 上工作正确。如果你的 DFA 在所有可能的由 $1$ 到 $n+1$ 的整数组成的数组 $a_1, a_2, \dots, a_n$ 上都能正确工作,则认为它总体上是正确的(因此,不建议使用概率性解法)。

对于 $n = 4$,我们将在所有可能的数组上测试你的 DFA。对于 $n = 250$,我们无法在所有可能的数组上进行测试,因此我们将在少于 5000 个特意挑选的数组上进行测试。本题共有两个测试点;这两个测试点都将有效地检验你的方法是否能同时在许多数组上正确工作。

输入格式

一个整数 $n$,其值等于 $4$ 或 $250$。

输出格式

第一行,输出一个正整数 $q$($1 \le q \le 4000$),表示你的 DFA 的状态数。

接下来的 $q$ 行中,第 $i$ 行输出 $n + 2$ 个整数 $\delta(i - 1, 0), \delta(i - 1, 1), \dots, \delta(i - 1, n + 1)$。它们都必须在 $-(n + 1)$ 到 $q - 1$ 之间(含两端),并对应于自动机的转移。注意,所有数字都必须在此范围内:即使状态 $i$ 和输入数字 $j$ 的某种组合在任何合法输入上都永远无法到达,你指定的 $\delta(i, j)$ 的值仍必须在 $[-(n + 1), q - 1]$ 范围内。

样例

输入样例 1

4

输出样例 1

8
-3 0 0 1 0 0
2 1 1 1 1 1
-1 3 2 2 2 2
4 3 3 3 3 3
-5 4 4 4 4 5
6 5 5 5 5 5
-2 6 7 6 6 6
-4 7 7 7 7 7

说明

样例中的答案是一个非常无聊的自动机,它使用四轮扫描来检查数组是否包含数字 3、1、5 和 2(按此顺序)。每一轮扫描实际上只使用两个状态,分别对应于它在当前轮中是否已经找到了它正在寻找的数字。如果它到达了数组的末尾(字符 0)而没有找到所需的数字,它会立即停机,并宣布该数字确实缺失。否则,它将继续使用下一轮扫描来寻找下一个数字。最后,如果它找到了所有四个所需的整数,那么数字 4 必然缺失。因此,它没有进行第五轮扫描来寻找数字 4(但它本可以在不违反自动机状态数和使用扫描次数限制的情况下这样做)。

当然,这种朴素的方法对于 $n = 250$ 是完全无法工作的,需要更好的方法。样例存在的主要目的是为了说明输出格式。

Editorials

IDTypeStatusTitlePosted ByLast UpdatedActions
#1213EditorialOpen题解jiangly2026-03-06 00:36:00View

Discussions

About Discussions

The discussion section is only for posting: General Discussions (problem-solving strategies, alternative approaches), and Off-topic conversations.

This is NOT for reporting issues! If you want to report bugs or errors, please use the Issues section below.

Open Discussions 0
No discussions in this category.

Issues

About Issues

If you find any issues with the problem (statement, scoring, time/memory limits, test cases, etc.), you may submit an issue here. A problem moderator will review your issue.

Guidelines:

  1. This is not a place to publish discussions, editorials, or requests to debug your code. Issues are only visible to you and problem moderators.
  2. Do not submit duplicated issues.
  3. Issues must be filed in English or Chinese only.
Active Issues 0
No issues in this category.
Closed/Resolved Issues 0
No issues in this category.