zoukankan      html  css  js  c++  java
  • [CF1246E]To Make 1

    题目链接

    题意

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

    $$f(n)=egin{cases}n, & k mid 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 e 0$, 一定存在 $i<j$ 使得 $b_i=b_j=B$, 否则等式两边同时乘以 $k^B$ 即矛盾。将 $a_i, a_j$ 替换成 $f(a_i+a_j)$, 对应地替换 $b_i, b_j$ 为 $B-v_k(a_i+a_j)$. 此操作下,$sum_{i=1}^na_ik^{-b_i}=1$ 仍成立,而 $n$ 减小 $1$, 迭代执行此过程即可。

    现在我们只需要求是否存在 ${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))$.

  • 相关阅读:
    xt
    UVA 10200 Prime Time (打表)
    CodeForces 540B School Marks
    CodeForces 540C Ice Cave (BFS)
    poj 3250 Bad Hair Day(栈的运用)
    hdu A Magic Lamp
    hdu 4325 Flowers(区间离散化)
    hdu 5500 Reorder the Books
    V2X之标准
    V2X的前生今世
  • 原文地址:https://www.cnblogs.com/nealchen/p/CF1246E.html
Copyright © 2011-2022 走看看