题目大意
题目总结:M. Medical Parity
问题描述
给定两个长度为 的二进制字符串 (测试结果串)和 (奇偶校验控制串)。
在理想情况下,字符串 与 必须满足以下关系:
对于每一个位置 (), 是字符串 前 个字符中 ‘1’ 的数量对 2 取模的结果。
即:。
这意味着:
-
如果 的前 个字符中有奇数个 ‘1’,则 。
-
如果 的前 个字符中有偶数个 ‘1’,则 .
由于记录数据时可能存在错误,输入的 和 可能不满足上述规则。你需要通过翻转最少数量的位(将 ‘0’ 变 ‘1’ 或将 ‘1’ 变 ‘0’),使得修改后的 成为修改后的 的合法奇偶校验控制串。翻转操作可以在 或 的任意位置进行。
输出要求
输出使 成为 的合法奇偶校验串所需的最少总翻转次数。
样例解释
-
样例 1
输入:
根据 计算合法的校验串 :- : 前 1 位有 1 个 ‘1’(奇数),
- : 前 2 位有 2 个 ‘1’(偶数),
- : 前 3 位有 3 个 ‘1’(奇数),
- : 前 4 位有 3 个 ‘1’(奇数),
- : 前 5 位有 4 个 ‘1’(偶数),
计算得 ,与给定的 完全一致。
结论: 翻转次数为 0。
-
样例 2
输入:
根据 计算出的合法 应为 (见样例 1)。
对比给定的 ,只有第 3 位不同( 应为 1,给定为 0)。
结论: 只需翻转 的第 3 位,总翻转次数为 1。 -
样例 3
输入:
若要达成合法状态,一种最少翻转方案是:- 翻转 的第 1 位,使其变为 。
- 此时合法的 应为 。
- 对比原 ,只需再翻转 的最后一位(第 5 位)。
结论: 总共翻转了 2 次( 一次, 一次)。
思路讲解
,其中 是 前 个字符中 1 的个数。注意到 (定义 )。也就是说, 完全由 决定(反之亦然)。所以你实际上只需要确定一个最终的 (或 ),另一个就自动确定了。
(其实只要观察到了红字的这个约束,红字的这个东西,那么剩下来这个DP啊就非常容易了。)
1 | vector<array<ll,2>> dp(N+2,{INF,INF}); |
AC代码
AC
https://codeforces.com/contest/2181/submission/362133326
1 | /** |
心路历程(WA,TLE,MLE……)
[1 tool called]
好的,你在 VP,我给你一些递进的提示,你可以根据需要看多少:
提示 1:观察 和 的关系
,其中 是 前 个字符中 1 的个数。注意到 (定义 )。也就是说, 完全由 决定(反之亦然)。所以你实际上只需要确定一个最终的 (或 ),另一个就自动确定了。
提示 2:代价的刻画
假设你选定了最终的 ,那么 就确定了()。翻转的总代价就是:
把 代入后,每个位置的代价只取决于 和 。试着把它写成关于相邻 值的函数。
提示 3:DP 的思路
既然每一位的代价只依赖 和 ,你可以用一个很简单的 DP:设 表示确定了 且 ()时的最小总代价。转移时枚举 的取值,计算当前位在 和 上分别需要翻转多少位即可。
这个 DP 是 的,完全够用。
祝 VP 顺利!