QOJ #14942. 出 Bug 的绘画软件 II/ Buggy Painting Software II
ICPC 2025 沈阳站 C 题。通信题。好题!
属于我的非传统题做题记录
为什么单独开一篇
因为该题中文互联网上资料比较少,单独开一篇方便后人搜索。
本题中所有出现的数都是整数,\([l,r]\) 实际上指 \([l,r] \cap \mathbb Z\)。
题意:这是一道 run twice 通信题。你需要实现两个过程:
- 编码:给定 \(n\) 个值域在 \([1,m]\) 中的整数,你需要给每个数编码一个 \(3m\) 长 \([1,m]\) 中每个数恰好出现一次的序列 \(a_{i,j}\)。
- 交互库做局:交互库会将你上一步生成的序列用一个任意的非空二划分 \((S_0,S_1),S_0 \cap S_1= \varnothing,S_1 \cup S_0= [1,m]\) 来处理上一步输出的序列,得到一个 01 序列 \(b_i\)。
交互库可能自适应。
- 解码:你会收到交互库做局得到的 \(n\) 个序列 \(b_{i,j}\),然后你需要还原出原来的 \(n\) 个数。
数据范围:\(2 \le n,m \le 5 \times 10 ^5 ,n\times m\le 10 ^6\)
也就是说 \(n\) 的实际目的是为了多测,以下我们只考虑编码、解码一个数的情况。
一个直观的想法是前 \(m\) 个数放 \(1,2,\cdots,m\),这样我们可以知道 \(S_0\) 和 \(S_1\) 分别是哪些元素。
然后考虑将剩下的元素怎么放。有一点要求:对于任意一个非空二划分 \((S_0,S_1)\),不存在两个整数的编码经交互库做局后是相同的。而由于每个数都有出现次数限制,所以最好的办法就是循环位移。以下用循环左移来实现。
先考虑只用 \(m+1 \sim m\times 2\) 中的数循环左移。比如 \(m=3\) 时,我们每个数编码如下:
为了以下说明方便,我们忽略前 \(m\) 个数。令 \(p_i=a_{\ast ,i+m}\)。如果存在 \((S_0,S_1)\) 使得 \(\exist x,y \in [1,m],\forall i \in [1,m], f(p_{(i-x) \bmod m}) = f(p_{(i-y) \bmod m})\),那么这么做就是不可行的。
也就是存在一个数 \(t = x-y,t \neq 0\),由 \(i \to (i+t) \bmod m\) 的基环树是不连通的。
不妨令 \(t \in [1,m-1]\)。由基础的数论可知,上述的基环树不连通当且仅当 \(\gcd(t,m) \neq 1\)。只要 \(m\) 不为素数,这种情况就有可能发生。
怎么办?我们总共有 \(m\) 的空间没有使用。由伯特兰-切比雪夫定理可知,在 \([m,2m)\) 中一定存在一个质数 \(p\),任取一个即可。
如何解码?我的想法是这样的:
这样一个序列,一定有 \(S_{[1,x]} = S_{[p+m-i+1,m+p]},S_{[i+1,m]}=S_{[m+1,2m-i]},S_{[1,p-m]}=S_{[2m-x,p+m-i]}\),最后一段不传递信息,无需检验,用字符串哈希即可。
复杂度显然 \(\mathcal O(nm)\)
官解用的是 KMP,复杂度相同,可以获得更小的常数。

浙公网安备 33010602011771号