• Codeforces Round #671 题意及思路


    A题

    题意

    题目给出 $ t $ 组数据,对于每一组数据:
    给你一个长度为 $ n $ 的数字串,Raze和Breach两人轮流删数,从Raze开始。Raze每次可删除在奇数位上的数,Breach每次可删除在偶数位上的数(注意:删除后并不改变其他数的位置。也就是说,2069在删除2后,Breach可删除的数仍是0或9)。若最后剩下的数是奇数,则Raze赢,否则Breach赢。两人都会以最优策略操作。若Raze赢输出1,否则输出2。

    思路

    如果是奇数位数,那么最后剩下的是Raze的数,那么只要奇数位数上有奇数那他就赢了。
    如果是偶数位数,那么最后剩下的是Breach的数,那么只要偶数位数上有偶数那他就赢了。

    B题

    题意

    题目给出 $ t $ 组数据,对于每一组数据:
    把呈阶梯状的图形称为“阶梯”,把最长边为 $ X $ 的阶梯称为“X级阶梯”。如图是一个7级阶梯。如果一个“X级阶梯”可被 $ X $ 个边长为正整数的正方形恰好覆盖,那么称之为“好阶梯”。
    现有 $ n $ 个边长为 $ 1 $ 的正方形,问最多可以搭出多少个不同的“好阶梯”?

    思路

    不难发现(x)$ 2^n-1 $ 级阶梯是好阶梯,然后从最小的开始拼。

    C题

    题意

    题目给出 $ t $ 组数据,对于每一组数据:
    一种新型病毒感染了Codeforces,他的感染机制是:如果未感染者B在某场比赛开始前或开始后与感染者A积分相同,那么他将会被感染。一旦被感染,则无法被治愈。
    有 $ n $ 个用户和Killjoy在Codeforces,最初只有Killjoy被感染。Killjoy的初始积分为 $ x $ ,所有用户都有一个初始的积分,第 $ i $ 个用户积分为 $ a_i $ 。
    比赛定期在Codeforces举行,每场比赛可有任意数量用户参加,Killjoy不能参加。每场比赛后参与的用户积分会升降一个整数,且所有参与用户变化的总分和为 $ 0 $ 。
    问至少需要几场比赛可将所有用户感染?

    思路

    对于所有数据,都可以在第一场比赛将 $ N-1 $ 个人积分变成与Killjoy一致,在第二场比赛再感染最后一个用户,故答案不会超过2。那么只需要讨论为0或者为1的情况。
    当所有用户一开始积分就都是 $ x $ ,则答案为 $ 0 $ 。
    答案为 $ 1 $ 有两种情况:1.所有用户积分的平均数为 $ x $ 2.有 $ 1 $ 个用户积分为 $ x $ ,则第一场比赛只需把其他人调整到 $ x $ 。

    D题

    题意

    Sage的生日去商店买东西,有 $ n $ 件商品排成一行,每个商品都有一个价格 $ a_i $ (在D1中保证商品价格各不相同,而D2中可能相同)。Sage只会买价格比左右两边商品价格都严格低的商品(他不会买最左边和最右边的商品)。
    问最多能让Sage买几件商品?第一行输出最多能买的商品的数量,第二行输出一种方案。

    思路

    对于D1,只需要一个大一个小的排列就可以了。
    对于D2,考试的时候分了两类:
    先将商品按价格从大到小排序。
    如果是奇数个商品,那么先从大到小、从左到右把奇数位填满,再从大到小、从左到右把偶数位填满。
    如果是偶数个商品,那么先从大到小、从左到右把奇数位填满,再将价格第 $ n/2+1 $ 大的商品放在最后一个,最后从大到小、从左到右把偶数位填满。

    不过可以简化为:
    排序,先从小到大从左到右填满偶数位置,再将剩下的数从小到大从左到右填到奇数位置。

    E题

    题意

    题目给出 $ t $ 组数据,对于每一组数据:
    给定一个数 $ n $ ,将 $ n $ 的大于 $ 1 $ 的所有因数围成一个圈,问怎么排列可使相邻 $ 2 $ 个数互质的对数最少?第一行输出排列方法,第二行输出此时最少的相邻两个数互质的对数。
    题目保证给出的 $ n $ 个数的因数总和不大于 $ 2⋅10^5 $

    思路

    分类讨论,$ p_i $ 为质数。

    1. $ n=p_k $ ,答案为 $ 0 $ 。
    2. $ n=p_1 p_2 $ ,任何排列答案都是 $ 1 $ 。
    3. $ n=p_1^a p_2^b $ ,其中 $ a $ 或 $ b $ 大于1,(此处感觉需要脑洞大开)应该可以想到把这些数分成两组,其中一组全能被 $ p_1 $ 整除,另外一组全能被 $ p_2 $ 整除,显然在同一组的数都可以排在一起。那么要想让他们围成一个圈,只需要找 $ 2 $ 个数将他们连接起来,显然可以找到 $ p_1 p_2 $ 与 $ n $ 两个数,剩下构造排列方式就简单了。
    4. $ n=p_1^a p_2^b ⋯ p_k^r $ ,由第3类我们可以自然想到将因数分为 $ k $ 组,已所有 $ p_i p_{i+1} $ 以及 $ p_k p_1 $ 为分界点构造排列。

    F题

    题意

    平面上存在 $ n $ 个点,你可以任选一个点出发并遍历所有点(一个点可以经过多次)。从一个点出发时只能朝一个方向走,且必须在 $ t $ 时间内到达另一个点。你有至多一次机会往平面上添加一个点(不能与已知点重合),求一个最小的 $ t $ 使得你能遍历所有的点(包括你添加的那一个点)。

    思路

    显然 $ t $ 可以通过二分答案求解,那么关键在于 $ check $ 函数怎么写。
    首先可以判断在不添加点的情况下有哪些点是可以通过长度不超过 $ t $ 的边互相连通的,这个可以用并查集实现。然后根据连通块个数分类讨论。
    1.如果有 $ 1 $ 个连通块,那么不需要加点就可以互相连通,返回 $ true $ 。
    2.如果有 $ 2 $ 个连通块,可以直接暴力判断,看是否存在属于不同连通块的 $ 2 $ 个点能否通过加 $ 1 $ 个点连通。条件有 $ 2 $ 种,一个是 $ 2 $个点有一维坐标是一样的,另一维坐标相差不大于 $ 2t $ ;另一个是 $ 2 $个点的 $ x,y $ 轴坐标相差都不大于 $ t $。只要存在一对就可以返回 $ true $ ,否则返回 $ false $ 。
    如果大于 $ 2 $ 个连通块,我们先仔细考虑加一个点可以带来什么。加一个点,如果在 $ t $ 时间内可以走到其他所有连通块,那么就可以返回 $ true $ 。而这个点只能向 $ 4 $ 个方向走,故最多连通 $ 4 $ 个连通块。于是我们马上得出:
    3.如果有不少于 $ 5 $ 个连通块,则返回 $ false $ 。
    4.如果连通块个数为 $ 3 $ 或 $ 4 $ ,我们可以枚举新加的点的位置,然后判断能不能把所有的连通块接通。因为新的的点要连通 $ 3-4 $ 个连通块,所以他所在的行列都应该有已经存在的点,通过这个条件就可以暴力枚举新加的点的位置;而判断是否能把所有的连通块接通,可以将所有点通过“第一关键字为 $ x $ 轴坐标,第二关键字为 $ y $ 轴坐标”和“第一关键字为 $ y $ 轴坐标,第二关键字为 $ x $ 轴坐标”两种方式排序,通过 lower_bound() 可以找到新加的点在原来点阵的什么位置,在判断上下或者左右有是否可以连通的点。只要有任意一个点可连通所有的点,则返回 $ true $ ,否则返回 $ false $ 。

    总结

    这是上大学以来第一次打CF,第一次写博客,可能打得不好,现在写得也很乱。感觉和学长 $ Destin Histoire $ 差距在于做题/读题的速度,前面 $ A-D2 $ 做的太慢,其实 $ E $ 题的构造应该说不算困难,但是没有想出来。
    这也是我第一次过最后一题,其实用的算法并不是非常复杂,希望这是一个起点,以后的每一次比赛,以前的每一次比赛,都要尽力把这些题认真钻研出来。

    提交记录

    写的很乱,请多多包容!!!
    $ A $ 题: A
    $ B $ 题: B
    $ C $ 题: C
    $ D1 $ 题: D1
    $ D2 $ 题: D2
    $ E $ 题: E
    $ F $ 题: F

  • 相关阅读:
    Android进程的优先级说明
    Android的有序广播和无序广播(解决安卓8.0版本之后有序广播的接收问题)
    Android开发中常用Dialog(普通弹窗&时间选择器&日历选择器)
    Android的显示意图和隐式意图总结
    Android的启动模式
    怎么评论一段php语言文本单词one-hot编码的健壮性
    python 基础知识,解决模板引擎实现原理流程
    SQL----EXISTS 关键字EXISTS基本意思
    omcat启动Publishing failed with multiple errors
    AngularJs directive详解及示例代码
  • 原文地址:https://www.cnblogs.com/Mercury04/p/13698876.html
Copyright © 2020-2023  润新知