Loading

12.2 CW 模拟赛 T3. 四舍五入

算法

考虑如何判定 \(x\) 能否变成 \(y\)

从低位到高位逐位比较, 若它们当前位相同, 则不进行进位, 否则只有当 \(y\) 这一位为 \(0\)\(1\) 时才可能有解

具体原因为对 \(x\) 当前位四舍五入后, 该位会变成 \(0\) , 变成 \(0\) 以后, 前面的位如果进位, 那么当前位会变成 \(1\) , 显然一个位置不可能进位 $ \geq 2$ 次, 因此只能得到 \(0, 1\) 两种值中的一种

显然的, 我们考虑数位 \(\rm{dp}\)

首先我们考虑状态的设计, 根据上文提到的性质, 我们令 \(f_{i, 0 / 1 / 2}\) 表示考虑了从低位到高位第 \(i\) 位数字, 其中前一位不进位 / 一定进位 / 可进位可不进位的方案数

注意到状态转移时, 我们需要考虑 \(z\) 的限制, 具体的, 分类讨论 \(z\) 当前位置上的数字, 由上可知一定为 \(0, 1\) 或者与当前位相同无需进位

显然的, 状态转移的难点在于需要进位时的方案数, 考虑分类讨论

pAIjgmR.md.png

边界条件 \(f_{len + 1, 0 / 1 / 2} = 1\) 仅当搜出来的数 \(\leq x\) , 注意在这道题中, 前导 \(0\) 不影响答案
答案即为 \(f_{1, 0}\)

时间复杂度 \(\Theta (\omega T \lg V)\) , 其中 \(V\) 为值域, \(\omega = 10\)


简单复习, 属于比较好的数位 \(\rm{dp}\) 思维题

四舍五入解的性质

考虑 \(y\) 作为 \(x\) 的四舍五入解, 也就是 \(y\) 可以通过若干次四舍五入变成 \(x\) 时, \(y, x\) 之间的关系

首先观察到, 一次四舍五入操作, 相当于把自己清 \(0\) 之后是否向上进位 \(1\)

那么我们这样考虑, 枚举 \(i : [1, len]\)

  • 如果 \(x_i = y_i\) 成立, 那么不进行操作
  • 否则
    • \(x\) 这一位不为 \(0/1\) , 那么显然无解
    • 其他情况需要考虑前一位能否进位

所以我们可以记录之前的进位情况, 然后才能处理
后面的数位 \(\rm{dp}\) 同样利用了这些性质

求出种类数

我们现在要构造 \([0, x]\) 区间中, 能通过若干次四舍五入变成 \(z\)\(y\) 的个数
不难想到数位 \(\rm{dp}\)

我们从低位到高位处理, 这样才方便处理进位, 这是与传统数位 \(\rm{dp}\) 不同的地方

你可能想问: 这种情况下如何处理 \(limit\) , 我们如何知道怎样才能不超出范围限制
其实和普通的限制是一样的, 你思考只要出现了当前位置比 \(x\) 的当前位置大或小的数, 对高位就一定有/没有约束, 只有相等的情况下, 才会继承之前的约束
到最后如果约束成立返回 \(1\) , 否则返回 \(0\) , 记忆化搜索会解决一切效率问题

解决了枚举方式的问题, 我们去解决进位标记的问题
pAIjgmR.md.png

这样子我们可以构造合法解了:

  • \(z\) 的这一位为 \(0/1\)
    根据进位条件推当前的进位情况, 当前数字枚举可得
  • 否则只能和 \(z\) 这一位数字相同
    根据进位条件反推当前的数字

总结

善于归纳性质, 注意数位 \(\rm{dp}\) 的特殊实现方式

数位 \(\rm{dp}\) 有两种实现方式, 具体的:

  1. 从高位往低位推, 使用 \(limit\) 标记
  2. 从低位往高位推, 使用递推的大小比较

附: 感谢 \(\rm{qcz}\) 大佬让我最终搞懂了这个题, 也明白了数位 \(\rm{dp}\) 的一些性质

代码是抄袭借鉴的 \(\rm{qcz}\) 大佬, 不放了


操作类问题一定要先把操作的方式搞清楚

posted @ 2024-12-03 15:28  Yorg  阅读(16)  评论(0)    收藏  举报