题意简述
一堆01
串是 dictionary 仅当其中没有一个串为另一个的前缀,且每个串都不含子串00
。
一个 dictionary $S$ 的 cost,是所有01
串 $s$(不仅包含 $S$ 中的串)的 cost 的和。
对于一个01
串 $s$,若其为 $k$ 个 $S$ 中串的前缀,则其 cost 为 $\sum\limits_{j=1}^k\lfloor1+\log_2j\rfloor$。
$t$ 组询问大小为 $n$ 的 dictionary 的 cost 的最小值,$t\le 5\times 10^4, 2\le n\le 10^{15}$。
主要思路
首先 $f(k)=\sum\limits_{j=1}^k\lfloor1+\log_2j\rfloor$ 可以在 $O(\log n)$ 预处理后 $O(1)$ 计算。
设 $D(n)$ 为构造大小为 $n$ 的 dictionary 的最小代价,则 $D(1)=1$。
我们把串扔到 trie 上,那么显然地,$D(n) = f(n)+\min\limits_{i\le k<n}\{f(k)+D(k)+D(n-k)\}$。这里 $k$ 是枚举左子树的叶子个数,$f(k)$ 是因为左边的串(因为不能出现00
)要以01
开头。($k=1$ 时则不需要加上 $f(1)$。)
可以证明 $D$ 是下凸函数,同时 $f$ 也是下凸函数,因此 $f(k)+D(k)+D(n-k)$ 也是下凸的。因此可以三分 $k$。于是我们可以 $O(\log^2n)$ 地求出任意一个 $D(n)$。
显然这不够。我们不妨枚举增量 $\delta$,每次求出最大 $n’$ 使 $D(n’)=D(n)+\delta\cdot(n’-n)$,其中 $n$ 是目前确定的最远 $D$ 值。
$n’$ 可以二分,且当 $n$ 足够大时,计算 $D(n’)$ 不会用到未确定的 $D$ 值。
可以证明 $\delta$ 是 $O(\log^2n)$ 级别。(经过尝试,$n\le 10^{15}$ 时,增量 $\delta$ 仅有 $1840$。)
于是可以 $O(\log^5 n)$ 预处理上述所有东西,每次询问再 $O(\log n)$ 二分一下即可。
参考代码
1 |
|