欢迎光临散文网 会员登陆 & 注册

[Codeforces is All You Need] CR 843 ABCD (1775ABCD) - Solution

2023-01-11 00:22 作者:故寓诸无竟  | 我要投稿


题目简述

        Problem A1 / A2:给定一个长度为n的只含字母'a'和字母'b'的字符串s,判断能否按顺序划分成非空的三个子串a%2Cb%2Cc,使得b的在字典序意义下,要么同时不比a%2Cc大,要么同时不比a%2Cc小。

        Problem B:给定一个长度为n的序列c。判断能否将c划分成两个不同(指所取的下标不同)的非空子序列ab,使得子序列中元素按位或的结果相等。

        Problem C:给定n%2Cx,解方程

n%5C%26%20(n%2B1)%20%5C%26%20...%20%5C%26m%20%3D%20x

        其中m%5Cge%20n。如果解存在,要求给出最小的解。

        Problem D:给定一个长度为n的数组a。如果a_ia_j不互质,则在i%2Cj之间连一条边。给定起点和终点1%5Cle%20s%2Ct%5Cle%20n,求最短路径,要求输出其中一种行走方案。

        原题目地址:https://codeforces.com/contest/1775

思路

        Problem A1 / A2:一个小小的分类讨论题目,不想多说,详见代码。

        Problem B:按位或操作相当于集合取并集。要想两个子序列不同,最简单的制造不一致的方法是选择一个被ab公共部分代表的集合包含的元素c_i,使得a不含c_ib包含c_i。如果连这种最简单的情形都无法成立,则无解。

        因此只需要依次判断每个元素的各个二进制位是否独自潇洒(我是指是不是只有它在这一位上为1)。对于元素c_i,一旦存在这么一个潇洒的二进制位,意味着它不可能被其它任何元素组代表的集合组的并集所包含。反之,把其它元素全选上,再利用c_i就可以按前述策略制造不一致。用一个桶记录一下各个位上1出现的个数,可以轻松完成判断,复杂度为O(%5Csum_%7Bi%3D1%7D%5E%7Bn%7D%20k_i),其中k_i表示c_i的二进制位中1的数目。

        后话:虽然非常浅显,但是可以硬来证明一下最开始提到的情形确实是“最简单的情形”,我将直接使用用集合的语言来说明。这个“最简单”是指所有可行的集合序列c,均存在对应的集合c_i和某个下标序列%5Cpi,使得:

c_i%20%5Csubseteq%20%5Cbigcup_%7Bj%3D1%7D%5E%7Bt%7D%20c_%7B%5Cpi_j%7D%2Ci%5Cnotin%20%5Cpi

        开证。因为集合序列c可行,因此存在下标序列a%20%5Cne%20b

%5Cbigcup_%7Bu%3D1%7D%5Ep%20c_%7Ba_u%7D%20%3D%20%5Cbigcup_%7Bv%3D1%7D%5E%7Bq%7Dc_%7Bb_v%7D

        由于a%20%5Cne%20b,因此存在b_e%20%5Cnotin%20a,使得:

c_%7Bb_e%7D%20%5Csubseteq%20%5Cbigcup_%7Bv%3D1%7D%5E%7Bq%7Dc_%7Bb_v%7D%20%3D%20%5Cbigcup_%7Bu%3D1%7D%5E%7Bp%7Dc_%7Ba_u%7D

        令%5Cpi%20%3A%3D%20a%2Ci%3A%3Db_e,这就完成了证明。

        Problem C:按位与操作相当于集合取交集,所以伴随m,左式会越来越小。在这一长串连续按位之中,左式是以何种方式变小呢?例如:

n%3D(%5Ccdots%2001110)_2

        我们惊讶的发现,和n%2B1按位与一下并不会影响结果,因为除了最低位,二者完全一致,而最低位已经是0了,无法被按位与改变。而:

n%2B2%20%20%3D%20(%5Ccdots%2010000)_2

        一旦它参与进来,连续的三个1将无一幸免永远变成0。事实上,这一规律具有普适性。即对于任意位置的连续1当且仅当在m达到在这些连续1的位置恰好变成了0且连续1的最高位再高一位由0变成1时,才会将这一段连续1一并永久变为0

        于是,可能的关键节点不超过63个(当然,其实只有这个数的一半左右)。因此我们可以枚举n的二进制表示中所有连续1片段,计算其对应的m节点,以及按位与的最终结果。这里不详述计算方案,最后的复杂度是O(1)

        Problem D:原始的图太大了,没有办法直接建图再跑BFS。但是节点是以互质关系来确定连接的,因此我们可以考虑从质因子出发做文章。st如果不直接相连,说明它们没用公共质因子(也就是互质了)。如何让它们连起来呢?需要找到一些中介。考虑一阶的情形,比如86有公共质因子2615有公共质因子3,这就把s%3D8t%3D15连上了。有了这一思考的基础,我们为什么要以数组元素为节点建图呢?

        直接以质因子为节点建图,这样每一个数组元素意味着若干个质因子之间的连接关系。这样边%5Cleft%3Cx%2Cy%20%5Cright%3E就表示“从包含某个质因子x的数出发,经过边所代表的数组元素,可以与另一个包含质因子y的数相连”。每个数组元素至多产生2%20%5Ctimes%20%5Cbinom%7B5%7D%7B2%7D%20%3D%2020条边(双向边存成两条有向边),这样新图仅包含约20000个节点和6000000条边,直接使用BFS求最短路,复杂度为O(V%2BE)。当然,需要一些琐碎的操作记录一条最短路径。

后记

        代码的github地址:https://github.com/cnzzx/AlgorithmCompetitions。

        A题的分类讨论花了我50分钟。不然E是有机会做的。烦躁。


[Codeforces is All You Need] CR 843 ABCD (1775ABCD) - Solution的评论 (共 条)

分享到微博请遵守国家法律