[CF1246E]To Make 1

题目链接

题意

一开始给出 $n$ 个不被 $k$ 整除的正整数 $a_1, a_2, \ldots, a_n$, 每次操作可以把两个数 $x, y$ 删去,放入 $f(x+y)$, 其中

$$f(n)=\begin{cases}n, & k \nmid n;\\f(n/k), & k \mid n.\end{cases}$$

求一个合理操作方法使最后只剩下一个 $1$, 或说明不能这么做。

  • $n \le 16$
  • $\sum_{i=1}^n a_i \le 2000$

题解

妙题。首先肯定想一般的子集 DP, $O(3^n(\sum a_i)^2/\mathrm w)$ 的时间相当爆炸。

但是我们发现这么操作以后结果一定形如 $\sum_{i=1}^na_ik^{-b_i}$.

而反过来,如果已知 $\{b_i\}$, 我们可以构造操作序列:取 $\max\{b_i\}=B$. 如果 $B=0$ 一定有 $n=1, a_1=1$, 已经做完;如果 $B \ne 0$, 一定存在 $i

现在我们只需要求是否存在 $\{b_i\}$ 使得 $\sum_{i=1}^na_ik^{-b_i}=1$ 了。我们可以这么设计状态:$g(S, m)$ 表示是否存在 $\{b_i\}$ 使得 $m=\sum_{i \in S}a_ik^{-b_i}$.

初值 $g(\emptyset, 0)=T$;

转移考虑每次加入一个 $b_i=0$ 的项,$g(S, m) \overset{\vee}\gets g(S \setminus \{i\}, m-a_i)$; 或者把所有 $b_i$ 都加上 $1$, $g(S, m) \overset{\vee}\gets g(S, mk)$.

最终检验 $g(I, 1)$.

逆推转移即能还原 $\{b_i\}$, 再经上述构造还原出操作序列。用位集维护第一类转移,时间 $O(2^n(\sum a_i)(1+n/\mathrm w))$.

你可能感兴趣的:([CF1246E]To Make 1)