CF 2172H Shuffling Cards with Problem Solver 68!

因为 \(t\) 很大,所以首先需要观察操作,尝试形式化刻画出初始下标为 \(i\) 的位置变化后的位置。

首先这个操作看着就带有一种“折半”的想法,所以尝试分析 \(i\) 的二进制,这也正好能和 \(2^k\) 契合。
如果按照 \(1\sim 2^k\) 编号就会多引入 \(k\) 这一位,所以应该把下标平移为 \(0\sim 2^k - 1\)

可以看一下 \(k = 3\) 的表:\([0, 1, 2, 3, 4, 5, 6, 7]\to [0, 4, 1, 5, 2, 6, 3, 7]\),这个时候把对应位置的二进制写出来,会有好看的规律。

当然也是可以理性推导的,考虑分讨 \(i\) 二进制下第 \(k - 1\) 位:

  • 若为 \(1\),则可以表示为 \(1\times 2^{k - 1} + x\)\(i\) 最后的位置是在 \(2x + 1\)
  • 若为 \(0\),则可以表示为 \(0\times 2^{k - 1} + x\)\(i\) 最后的位置是在 \(2x\)
    经过这样分讨,很容易看出规律就是,\(i\) 在操作后所在的位置就是 \(i\) 二进制表示向低位循环移 \(1\) 位(最低位变为第 \(k - 1\) 位)的位置。

那么就可以知道对于最终结果为 \(i\) 的位置,对应到初始时就是 \(i\) 二进制表示下向高位循环移 \(t\) 位的位置。

接下来考虑求解字典序的问题。

首先考虑 \(t = 0\) 时,此时就相当于是求 \(s\) 所有循环移位中的最小字典序。
此时做法有很多,可以用最小表示法的方法,也可以带个 \(\log\) 用后缀数组,哈希二分 lcp 之类的。

不过在这题的变换下,这些做法还能不能用并不好直接看出来,所以还是需要继续分析一些性质。

发现在这题的变换下,二进制下第 \(i\) 位会对应初始时二进制第 \((i - t)\bmod k\) 位。

那么正常情况相邻下标之间的差是 \(2^0\),在二进制对应后下标之间的差就变成了 \(2^{(-t)\bmod k}\)
此时做的加法是二进制下循环的,也就是二进制第 \(k\) 位等同于二进制第 \(0\) 位,对应到 \(k = 3, t = 1\) 的例子就相当于是 \(4 + 2^{(-t)\bmod k} = 4 + 4 = (100)_2 + (100)_2 = (001)_2 = 1\),就知道了 \(4\) 的下一个应该是 \(1\) 了。

然后回到初始状态,考虑以 \(p\) 位置为开头的字符串,在变换后按顺序为 \(p, p + 2^{(-t)\bmod k}, p + 2\times 2^{(-t)\bmod k}, p + 3\times 2^{(-t)\bmod k}\cdots\),加法依然为上面说的二进制下循环加法。

因为在这个循环加法意义下有 \(2^{x\bmod k} + 2^{x\bmod k} = 2^{(x + 1)\bmod k}\),套用求解后缀数组的想法,可以划分成 \([p, p + 2^{(-t)\bmod k}], [(p + 2^{(1 - t)\bmod k}), (p + 2^{(1 - t)\bmod k}) + 2^{(-t)\bmod k}], \cdots\)
会发现这和求解后缀数组十分相似,依然是每次都可以让覆盖的前缀长度翻倍,只需要把扩展的循序改为距离自己依次为 \(2^{(-t)\bmod k}, 2^{(1 - t)\bmod k}, 2^{(2 - t)\bmod k}\cdots\) 的位置即可。

整个过程是有点抽象的,可以对着 \(k = 3\) 玩一玩。

时间复杂度为 \(\mathcal{O}(2^k k)\)

submission

posted @ 2026-01-16 15:34  rizynvu  阅读(2)  评论(0)    收藏  举报