• Atcoder做题随心记


    一些随意的记录

    AtCoder Regular Contest 106 DEF

    AtCoder Regular Contest 106 DEF

    AtCoder Grand Contest 006 BCDEF

    AGC006 BCDEF

    AtCoder Grand Contest 005 CDEF

    AGC005 CDEF

    AtCoder Grand Contest 004 CDEF

    AGC004 CDEF

    AtCoder Grand Contest 003 CDEF

    AGC003 CDEF

    AtCoder Grand Contest 002 DEF

    AGC002 DEF

    AtCoder Grand Contest 001 CDEF

    AGC001 CDEF

    AGC048D - Pocky Game

    D - Pocky Game

    (a_{i,j}) 表示 (A) 先手,只考虑 ([l,r]) 这段,(A) 要获胜第 (i) 个位置至少有多少石子

    (b_{i,j}) 表示 (B) 先手,只考虑 ([l,r]) 这段,(B) 要获胜第 (j) 个位置至少有多少石子

    肯定是越多越有利,因为一次可以拿任意多个,太多了也不会导致结果变差,所以这个状态是挺合理的

    按照一般的区间dp转移,只介绍 (a_{i,j}) 的, (b) 的基本一样,设第 (i) 个位置有 (c_i) 个石子

    1、如果 ({c_j} < {b_{i+1,j}}),那不管第 (i) 个位置有多少,直接拿光就赢了(([l+1,r]) 这段B先手赢不了),有 (a_{i,j}=1)

    2、({b_{i+1,j}} leq {c_j}),这时候要考虑两个点:

    Ⅰ、和A消耗,一个一个拿,此时为了让消耗玩后 ({c_j} < {b_{i+1,j}}),至少要 ({c_j} - {b_{i+1,j}} + 1)

    Ⅱ、消耗结束,B知道自己在 ([l+1,r]) 赢不了,干脆把第 (j) 堆直接拿完,变成 ([l,r-1]) 的A先手的游戏,此时为了胜利,消耗完后至少还要 (a_{i,j-1})

    综上,第二种情况 (a_{i,j}={c_j} - {b_{i+1,j}} + 1 + a_{i,j-1})

    code

    ARC105F - Lights Out on Connected Graph

    F - Lights Out on Connected Graph

    状态压缩。条件是二分连通图,把二分和连通分开处理

    (g_i) 表示点集为 (i),二分图的方案数,先预处理出点集中有多少边,然后枚举二分图的两部分的点集,连接两部分的点可以选也可以不选,加上 (2^k)

    然后算 (f_i),发现 (f_i) 要从 (g_i) 中减去不连通的数量。任意枚举一个点(代码中是编号最小的)所在连通块的状态,其他部分随意,方案相乘再减掉

    看代码比较容易懂,有一些备注 code

    ARC105E - Keep Graph Disconnected

    E - Keep Graph Disconnected

    又是博弈论。。。

    游戏的最后状态肯定只存在两个联通块,一个包含 (1),一个包含 (n), 且块内的边都连满了

    可以用完全图的边数减去没有连的边,设最后两个块大小为 (a,b),则总边数 (sum = frac{n imes (n-1)}{2} - a imes b)

    输赢和 (sum) 的奇偶有关,可以想到把 (n) 也分为两类讨论

    1、(n) 为奇数:(a,b) 一定是一奇一偶,那么 (sum) 奇偶确定,答案也就确定

    2、(n) 为偶数比较麻烦:

    假设初始时 (1)(n) 所在的连通块大小分别为 (x,y),根据 (x,y) 的奇偶性再分两类:

    A、(x,y) 一奇一偶,剩下的点为奇数个。所以奇数的联通块有奇数个,偶数的连通块若干,只有奇数可以改变奇偶性

    此时先手可以把 (x imes y) 变成自己想要的奇偶,如果要变成奇+奇,就先连一个奇数块到偶的那个,否则把一个奇数块连到奇数的那个

    然后如果后手连了一个奇数块,则先手也连一个奇数块到同一个(剩下偶数块,可以一一配对),奇+奇=偶,奇偶性不变,否则连其他的。

    B、(x,y) 奇偶性相同,若 (x,y) 都为奇数,则想要两个奇数的获胜,否则想要两个偶数的获胜,证明和上面差不多。。。

    code

    ARC105D - Let's Play Nim

    D - Let's Play Nim

    好玩的博弈论,有两个结论

    1、(n) 为奇数,后手必胜。此时相当于先手多放一次硬币,但从后手开始取,所以后手要保证所有堆的异或和不为 (0)。假设先手第一次放在了第 (x) 堆,则后手每一次都选择当前最大的放入第 (x) 堆,保证最后这一堆的数量大于其他所有的和,这样异或和一定不为 (0)

    2、(n) 为偶数,此时先手开始取。若所有数可以成双配对,则后手取胜,每次只要选一样的放就可以保证异或和为 (0)。否则先手获胜,和第一种类似,每次选取最大的放入同一堆,则这一堆一定大于其他所有的和

    code

    ARC104E - Random LIS

    E - Random LIS

    (n) 很小,可以先确定 (n) 个数的相对大小,得出LIS长度,再通过dp算出方案数相乘即可,具体方法:

    (f_{i,j,k}) 表示前 (i) 大的数,最大的在第 (j) 段,第 (j) 段放了 (k) 个数的方案

    有两个转移:

    1、放在新的一段 (f_{i,j,1}+=sumlimits_{j'=k'=1}^{j'<j,k'<i}{f_{i-1,j',k'}})

    2、前 (i-1) 个已经有一些放在第 (j) 段,假设长度为 (l_j),则有 ({l_j}-k+1) 个位置可以放,但第 (i) 个必须在最前面,概率为 (frac{1}{k})

    so (f_{i,j,k}+=f_{i-1,j,k-1} imes frac{(l_j-k+1)}{k})

    code

    ARC104D - Multiset Mean

    D - Multiset Mean

    直接做是一个复杂度爆炸的背包

    发现如果 (x) 确定,就可以把 (1-n) 的数都减去 (x) ,答案是加起来为 (0) 的方案数

    还是用类似背包的dp,(f_{i,j}) 表示用 (1-i) 的数字,和为 (j),的方案数

    (f) 数组可以预处理。注意到这个背包中商品的价值和体积特殊,可以用前缀和优化转移

    对于每个 (x) ,正数和负数的值域都确定,枚举 (j) 加和即可。注意 (0) 的特殊处理

    复杂度 (O(kn^3))code

    ARC104C - Fair Elevator

    C - Fair Elevator

    没想到这是个dp。。。

    (f[l][r]) 表示区间 ([l,r]) 这一段是否独立且符合条件。也就是说这一段所有区间都相交

    那么这一段长度 (len) 为偶数且所有 (a_i,b_i),满足 (b_i - a_i = len / 2),找出所有符合的数量 (>=len/2) 即为可行,但还要注意判断特殊情况:

    1、(a_i,b_i) 确定且在区间内但差值不满足

    2、(a_i,b_i) 有一个确定且在区间内,但另一个的位置已经确定

    然后再dp推出 (dp_i) 表示前 (i) 个能否满足

    code

    ARC102E - Stop. Otherwise

    E - Stop. Otherwise

    题目的本质就是对于每个 (i) 有一些 ((x,y)) 不能同时选,然后另外一些数随便选

    把这两部分的个数算出来。每个选了的数对可以选 (x)(y),有个 (*2) 的贡献,枚举选了多少个数对,隔板法再 ( imes 2^k)

    如果 (i) 是偶数,按照 (i/2) 选不选讨论

    code

    ARC102D - All Your Paths are Different Lengths

    D - All Your Paths are Different Lengths

    边和点很少而 (L) 挺大,容易想到利用进制构造,只要朴素利用进制的性质即可,下面以二进制为例介绍具体做法

    把一些个节点串成一条链,再在一段连上终点,再相邻两个点之间连接两条边,相当于二进制数每一位的 (1,0),代表 (1) 的权值赋为 (2^k)(k) 为距离终点的距离。然后从起点按照一定方法连边

    但用二进制会不满足数量限制,改为三进制即可

    code

    ABC176F - Brave CHAIN

    F - Brave CHAIN

    转换原题意:初始有(2)张牌,每次操作拿(3)张牌并从(5)张牌中丢弃(3)张,如果(3)张一样得分(+1)

    进行(dp)

    step 1

    (f_{i,j,k})表示进行(i)轮游戏后,手里剩下的牌为(i)(j)时的最大值

    枚举(i,j,k)和这轮游戏后手中的牌,复杂度(O(n^5))

    step 2

    如果当前手中的牌为(j,k),每一轮新拿的三张牌是确定的,一轮过后的(2)张牌只能从(5)张中选,共(10)种情况,复杂度(O(10 imes n^3))

    step 3

    可以按照(2)张牌有几张来自新拿的(3)张进行分类加速转移

    1、如果(2)张都来自新拿的,则可以从之前的任意状态进行转移,记录最大值即可。还要考虑丢弃的(3)张牌相同的情况分数(+1)

    2、如果有(1)张牌来自新拿的,另一张牌为(x),说明(x)来自之前的牌,则必须从有(x)的状态进行转移(还是记录最大值)。同样特殊考虑(3)张牌相同进行额外转移

    3、如果(j,k)均不来自新拿的,则丢弃的三张牌一定是新拿的,判断一下是否有分。从上一步的(j,k)转移

    观察发现,每次转移情况(1)的复杂度是常数,(2)的复杂度为(O(n)),但存在情况(3),复杂度并没有得到提高

    (3)的所有转移形式一致,不用暴力算,用一个变量记录加的分就好了。但如果选择情况(1,2)就不能获得(3)的加分,在转移的时候减去即可

    code

    ACL contest1

    题解在这

  • 相关阅读:
    C/C++程序员必备的15个编辑器和集成开发环境
    天猫浏览型应用的CDN静态化架构演变
    实用技巧:如何用 CSS 做到完全垂直居中
    JavaScript 字符串操作:substring, substr, slice
    Hybrid App 开发初探:使用 WebView 装载页面
    引领潮流!最顶尖的24个获奖网页作品
    HTML5编程之旅系列一:HTML5 Geolocation 初探
    JavaScript 秘密花园——对象的使用和属性操作
    提高效率!15款最好的 Bug 跟踪应用程序
    最常用的8款 PHP 调试工具,你用过吗?
  • 原文地址:https://www.cnblogs.com/whx666/p/13736658.html
Copyright © 2020-2023  润新知