Codeforces 康复训练 1

这里是康复训练 Codeforces 第一弹喵。

CF1986E

考虑按模 k k k 得数划分成若干个集合,序列长度为偶数则每个集合元素为偶数个;序列长度为奇数则有且只有一个集合大小为奇数,剩余全为偶数。

考虑性质,若对于同一个集合内的元素 a i ≤ a j ≤ a k ≤ a t , i < j < k < t a_i \leq a_j \leq a_k \leq a_t,i<j<k<t aiajakat,i<j<k<t,显然最佳配对为 ( a i , a j ) ( a k , a t ) (a_i,a_j)(a_k,a_t) (ai,aj)(ak,at)

序列长度为偶数是好算的,奇数的情况类似,考虑将大小为奇数的集合单独拿出来计算。考虑枚举放在中心的数的位置,利用前缀和后缀和计算即可。

CF1987C

考虑每个位置变为 0 0 0 的时间,首先有 t n = a n t_n=a_n tn=an,考虑倒推。

对于当前的 a i a_i ai 和最后一个点 a i + 1 a_{i+1} ai+1 分类讨论:若 a i ≤ a i + 1 a_i \leq a_{i+1} aiai+1,则 t i = t i + 1 + 1 t_i=t_{i+1}+1 ti=ti+1+1;若 a i > a i + 1 a_i>a_{i+1} ai>ai+1 a i + 1 a_{i+1} ai+1 会一直减小,则 a i a_i ai 也一定会一直减小,则 t i = a i t_i=a_i ti=ai

不确定是哪种情况取 max ⁡ \max max 就行。

CF1987D

Alice 显然会选择此时最小的可取的蛋糕。

对于一种蛋糕,Alice 只需要 1 1 1 回合就可以获得贡献,而 Bob 需要蛋糕个数 c n t i cnt_i cnti 回合,所以 Bob 可以选择舍弃这种蛋糕,为自己攒下 1 1 1 回合。

考虑 dp,令 f i , j f_{i,j} fi,j 表示前 i i i 种蛋糕,Bob 攒了 j j j 个回合最多能取多少种蛋糕,有 f i , j = max ⁡ ( f i − 1 , j − 1 , f i − 1 , j + c n t i + 1 ) f_{i,j}=\max(f_{i-1,j-1},f_{i-1,j+cnt_i}+1) fi,j=max(fi1,j1,fi1,j+cnti+1)

答案即为总蛋糕种数减去 Bob 最多能拿多少种蛋糕。

CF1985H1

真特么难写。首先思路很自然的是枚举填满哪一行(哪一列),考虑怎么统计答案。

以填行为例,填列同理。若这一行穿过一个连通块,则将这个连通块剩余的部分加进该行的答案;若没有穿过连通块但是与该连通块有接触(即相连),则将整个块加入答案。

CF1985H2

类似于 Easy Version,我们依然考虑通过行 + + + 列的形式统计答案,但是由于有的连通块会被计算两次,我们要考虑去重。设 m i , j m_{i,j} mi,j 表示 同时对第 i i i 行,第 j j j 列有贡献 的连通块大小总和。

设一个连通块上下边界 [ x 1 , y 1 ] [x_1,y_1] [x1,y1],左右边界 [ x 2 , y 2 ] [x_2,y_2] [x2,y2],则对于 ∀ x ∈ [ x 1 − 1 , y 1 + 1 ] , y ∈ [ x 2 − 1 , y 2 + 1 ] \forall x \in [x_1-1,y_1+1],y \in [x_2-1,y_2+1] x[x11,y1+1],y[x21,y2+1],有 m i , j + = s i z m_{i,j}+=siz mi,j+=siz

相当于矩阵加,单点查询,直接二维差分维护即可。

link

CF1983D

首先对于每一次相邻元素交换,都会使逆序对数 ± 1 \pm 1 ±1,而对于非相邻元素的交换,等价于若干次相邻元素交换,故我们只考虑相邻元素交换。

考虑直接判断序列 a , b a,b a,b 逆序对数奇偶性是否相同即可。

啊啊啊啊怎么有人没离散化数组越界了我服了啊啊啊。

CF1984C2

一个好发现的事实是:当前缀和为最小值时,进行一次操作 2 2 2 一定不亏,且该次操作是使最终结果最大的充要条件。

对于全程都 > 0 >0 >0 的数组来说结果为 2 n 2^n 2n

考虑最低点小于 0 0 0 的情况,枚举所有最低点为关键点对答案的贡献,为了不重复计数,在它之前的所有最低点均不进行操作 2 2 2

首先 ≥ 0 \geq 0 0 时取不取均可,记前缀和数组 s 1 ∼ s i s_1 \sim s_i s1si ≥ 0 \geq 0 0 的个数为 c n t i cnt_i cnti,那么每个关键点对答案的贡献为 2 c n t i − 1 × 2 n − i 2^{cnt_{i-1}} \times 2^{n-i} 2cnti1×2ni,计算即可。

可以预处理 2 2 2 的幂次提高运行效率。

CF1982D

记整个图中两种颜色和的差为 delta \text{delta} delta,每个方阵两种颜色的山个数差为 c 1 , ⋯   , c p c_1,\cdots,c_p c1,,cp,那么问题就等价于给每个 c i c_i ci 一个系数,判断方程

∑ i = 1 p c i x i = delta \sum_{i=1}^p c_i x_i=\text{delta} i=1pcixi=delta

是否有解,只需要判断 gcd ⁡ i = 1 p c i ∣ delta \gcd_{i=1}^p c_i|\text{delta} gcdi=1pcidelta 即可。

CF1981C

问题等价于对于若干组 ( x , y , k ) (x,y,k) (x,y,k),判断是否能从 x x x 经过恰好 k k k × 2 / × 2 + 1 / ÷ 2 \times 2/ \times 2+1 / \div2 ×2/×2+1/÷2 到达 y y y,由于操作可逆,为了方便讨论我们不妨假设 x < y x<y x<y

操作等价于将 x x x 二进制下整体左移一位,最后一位为 0 0 0/左移一位,最后一位为 1 1 1/右移一位。

猜想:记 x , y x,y x,y 二进制下公共前缀长度 L L L x x x 二进制下位数为 L x L_x Lx y y y 二进制下位数为 L y L_y Ly。那么 x x x 需要先进行 L x − L L_x-L LxL 次操作删除所有不合法位置,再进行 L y − L L_y-L LyL 次操作使最高位对齐,并且使剩余位置与 y y y 匹配。

所以我们判断有解当且仅当 L x + L y − 2 L ≤ k L_x+L_y-2L \leq k Lx+Ly2Lk L x + L y − 2 L L_x+L_y-2L Lx+Ly2L k k k 的奇偶性相同。

link

CF1979D

先记录几个小性质:

1. 1. 1. 若存在一个长度 > k >k >k 的连续相同字符子串,一定需要破开,否则不满足 k − p r o p e r k-proper kproper

2. 2. 2. 该次操作最多破开一个串,显然两个 > k >k >k 的连续子串无法同时破开,故此时无解。

3. 3. 3. 若存在一个长度 > k >k >k 的串,那么破开方法唯一:保留后 k k k 位,将前面全部放到字符串最后。因此可以推断该串长度不能超过 2 k 2k 2k

此时确定长度 > k >k >k 的连续子串不超过 1 1 1 个,分开讨论:

若有 1 1 1 个,按照唯一方式断开后检验即可。

若无,考虑最终串的形式一定为若干个长 k k k 连续相同子串构成,且 01 01 01 交替。

由于只能进行一次操作的特殊性,若有解,则整个串中要么没有长度不为 k k k 的连续子串,直接 p = n p=n p=n 即可;要么有 2 2 2 个且长度和为 k k k 2 2 2 个不完整的串在整个串的末尾

CF1975D

蓝棋子 b b b 必须走在红棋子 a a a 走过的地方才有贡献。

所以其实 a a a 怎么走不重要,重要的是 b b b 怎么走,我们可以考虑先让两点相遇或距离为 1 1 1,此时已经可以忽略 a a a 的走位,因为 a a a 一定可以提前覆盖使 b b b 经过的位置为红色。

需要特殊说明的是:若 a , b a,b a,b 距离为 1 1 1,则需要先将 b b b 走到 a a a,再考虑接下来怎么走。

然后就变成了一个经典问题:以指定点 r t rt rt 为根,遍历每一个点一遍最少需要多少步。

这个问题的弱化版是 r t rt rt 出发遍历所有点一遍回到 r t rt rt 的步数。对于这个问题,我们考虑每个点对答案的贡献,到达每个点(除 r t rt rt)都需要 1 1 1 步,对于每个儿子都一定会再回来一次,那么答案就是 n − 1 + ∑ i = 1 n s o n i = 2 n − 2 n-1+\sum_{i=1}^n son_i=2n-2 n1+i=1nsoni=2n2

我们回到现在这个问题,我们不必回到原点,说明可以省去一条链的贡献,那么答案就是上面的答案 2 n − 2 − m a x l + 1 = 2 n − 1 − m a x l 2n-2-maxl+1=2n-1-maxl 2n2maxl+1=2n1maxl,其中 m a x l maxl maxl 为以 r t rt rt 为根下的最长链长度。

CF1988D

赛时想贪心发现怎么都能举出反例,想 DP 却也无法明确状态,看了题解才恍然大悟。

因为每次取出的点不相邻,所以如果给每个点被取出的时刻打上时间戳,周围的点一定与它不同(可以在它之前也可以在它之后)。

d p u , i dp_{u,i} dpu,i 表示以点 u u u 为根的子树内都被消除且点 u u u 的时间戳为 i i i 的最小代价,直接做即可,时间复杂度 O ( n log ⁡ n ) \text{O}(n \log n) O(nlogn)

CF1975E

判断链的合法性:链中至多有一个点向两棵子树都有边。如果给每个点 − 1 -1 1,给其父亲 + 1 +1 +1,那么会有两种可能:

1. 1. 1. 自上到下一条链, 1 , − 1 1,-1 1,1 各一个, 1 1 1 为白点(我们把不存在的 0 0 0 点也计入)。

2. 2. 2. 跨过一个点经过两个子树,两个 − 1 -1 1,两个 1 1 1,权值为 1 1 1 的点中,一黑一白且两点构成父子关系

这样做是线性的,再加个 set 大力维护一下就行。

或者这题也可以树剖,没有儿子的点至多两个,每次找到这两个点,查询路径上黑点个数即可, O ( n log ⁡ 2 n ) \text{O}(n \log^2 n) O(nlog2n)

CF915G

先只考虑询问元素上界为 k k k 的情况,我们发现这个形式很难直接计算,可以考虑计算 gcd ⁡ ∈ [ 2 , k ] \gcd \in [2,k] gcd[2,k] 的情况数。

f k , i f_{k,i} fk,i 表示上界为 k k k 时, gcd ⁡ = i \gcd=i gcd=i 的方案数,那么有关系式: f k , i = f ⌊ k i ⌋ , 1 f_{k,i}=f_{\lfloor \frac{k}{i} \rfloor,1} fk,i=fik,1。那么原式子就可以写为:

f k , 1 = k n − ∑ i = 2 k f k , i = k n − ∑ i = 2 k f ⌊ k i ⌋ , 1 f_{k,1}=k^n-\sum_{i=2}^k f_{k,i}=k^n-\sum_{i=2}^k f_{\lfloor \frac{k}{i} \rfloor,1} fk,1=kni=2kfk,i=kni=2kfik,1

换个更舒服的形式:

f k = k n − ∑ i = 2 k f ⌊ k i ⌋ f_k=k^n-\sum_{i=2}^k f_{\lfloor \frac{k}{i} \rfloor} fk=kni=2kfik

此时时间复杂度 O ( k k ) \text{O}(k \sqrt{k}) O(kk ),还要取模很多次,很劣啊。

考虑差分的形式, f k − f k − 1 = k n − ( k − 1 ) n + ∑ i = 2 k − 1 f ⌊ k − 1 i ⌋ − ∑ i = 2 k f ⌊ k i ⌋ f_k-f_{k-1}=k^n-(k-1)^n+\sum_{i=2}^{k-1} f_{\lfloor \frac{k-1}{i} \rfloor}-\sum_{i=2}^k f_{\lfloor \frac{k}{i} \rfloor} fkfk1=kn(k1)n+i=2k1fik1i=2kfik

那么现在的难题就是 ∑ i = 2 k − 1 f ⌊ k − 1 i ⌋ − ∑ i = 2 k f ⌊ k i ⌋ \sum_{i=2}^{k-1} f_{\lfloor \frac{k-1}{i} \rfloor}-\sum_{i=2}^k f_{\lfloor \frac{k}{i} \rfloor} i=2k1fik1i=2kfik 怎么算,它等于 − f 1 + ∑ i = 2 k − 1 ( f ⌊ k − 1 i ⌋ − f ⌊ k i ⌋ ) -f_1+\sum_{i=2}^{k-1} (f_{\lfloor \frac{k-1}{i} \rfloor}-f_{\lfloor \frac{k}{i} \rfloor}) f1+i=2k1(fik1fik),注意到 ⌊ k − 1 i ⌋ ≠ ⌊ k i ⌋ \lfloor \frac{k-1}{i} \rfloor \neq \lfloor \frac{k}{i} \rfloor ik1=ik 当且仅当 i ∣ k i|k ik,且此时两者差必为 1 1 1

此时理论能过,也的确有人这么过了,但我卡不过,令人感慨。

Update:过了。不过谁能解释一下为什么快速幂预处理改成线性之后快了这么多。link

CF1992G

首先对于任意子序列 b b b,一定有 mex ( b , ∣ b ∣ + 1 ) ≥ ∣ b ∣ + 1 \text{mex}(b,|b|+1) \geq |b|+1 mex(b,b+1)b+1

在此基础上,在 1 ∼ ∣ b ∣ + 1 1 \sim |b|+1 1b+1 之间有 1 1 1 个数,那么就会额外产生 1 1 1 的贡献;在 1 ∼ ∣ b ∣ + m 1 \sim |b|+m 1b+m 之间有 m m m 个数,就会额外产生 m m m 的贡献。

那么贡献计算式子为

∑ i = 0 n C n i ( i + 1 ) + ∑ j = 1 i j ⋅ C min ⁡ ( n , i + j ) j ⋅ C max ⁡ ( 0 , n − i − j ) i − j \sum_{i=0}^n C_n^i(i+1)+\sum_{j=1}^i j \cdot C_{\min(n,i+j)}^j \cdot C_{\max(0,n-i-j)}^{i-j} i=0nCni(i+1)+j=1ijCmin(n,i+j)jCmax(0,nij)ij

CF1994D

你不觉得这么多组样例都是 YES \text{YES} YES 很奇怪吗???

操作可逆,我们倒着考虑,当前有 n n n 个数,根据抽屉原理,必有两个模 n − 1 n-1 n1 相同的,那么他们的差为 n − 1 n-1 n1 的倍数,可以连边。

之后每次删除一个点,重复操作即可。

CF1994E

性质1:总能通过裁剪叶子使子树达到想要的数值。

性质2:树的结构并不重要,只在乎点数。

那么问题就已经转化为对于 n n n 个取值区间 [ 1 , a i ] [1,a_i] [1,ai],使得 a i a_i ai 的或和最大。

性质3: max ⁡ a i \max a_i maxai 一定选,其决定二进制位数上界。

那么就是在此基础上,补齐二进制上0的位置,之后的事情和之前做过的一道 CF 题很像啊。

CF1994F

这真的是 div.1+2 ????真送吧。

有 NPC 的边一定保留,那么就是在此基础删没有 NPC 的边使其成为欧拉回路。有欧拉回路的条件是度数为奇数的点的个数为偶数。

CF1992F

首先我们明确,从当前左端点 l l l 出发,一定会到达最右的合法位置,否则一定不优(下一个区间多一数不如少一数)。

1 0 5 10^5 105 内,因数最多的数是 83160 83160 83160,共 128 128 128 个因数。

f i f_i fi 表示当前区间内是否能构成第 i i i 个因数,转移显然。

CF1992E

n a − b na-b nab 的位数一定不超过 6 6 6

枚举所有情况,枚举 a a a 即可。

CF1989D

不懂就问,大家为什么都在 dp 哇?

每种材料独立,且铸造一把武器后熔毁一定更优。将所有的武器铸造方法按 a i − b i a_i-b_i aibi 从小到大排序,依次遍历即可。

在这个过程中,用优先队列维护当前剩余铁的数量,用 map 维护剩余铁为 x x x 个的铁的种类数,会比正常做多一个 log ⁡ \log log 但也在承受范围内。

link

CF1986F

发现只有删割边才能使答案变小,但是不好统计答案。

考虑边双缩点后形成一棵树,树上的每条边都是割边,查询最大值即可。

CF1973C

n n n 是偶数,我们大胆猜测有 n 2 − 1 \frac{n}{2}-1 2n1 个局部最大值的方案一定存在。

对于中间两组可选项,我们贪心的选择最小值较大的一组,并将 n ∼ n 2 + 1 n \sim \frac{n}{2}+1 n2n+1 依次从小到大加上去,最小值有 ≥ n + 2 \geq n+2 n+2

证明:最小值最小为 2 2 2,最大值最小为 n 2 + 1 \frac{n}{2}+1 2n+1,怎么加都至少是 n + 2 n+2 n+2

然后把 n 2 ∼ 1 \frac{n}{2} \sim 1 2n1 从小到大的加上去,那么它一定有 ≤ n + 1 \leq n+1 n+1

那么我们的合法方案就构造完成了。

CF543D

很自然想到换根 dp。

考虑 1 1 1 为根时怎么做,令 f u , 0 / 1 f_{u,0/1} fu,0/1 表示以 u u u 为根子树内有无坏边的方案数,因为子树内有一条坏边都意味着 u u u 向上的连边必须全为好边,那么有

f u , 0 = ∏ v f v , 0 f_{u,0}=\prod_v f_{v,0} fu,0=vfv,0

f u , 1 = ∏ v ( 2 f v , 0 + f v , 1 ) − 1 f_{u,1}=\prod_v (2f_{v,0}+f_{v,1})-1 fu,1=v(2fv,0+fv,1)1

具体地,子树无坏边时,边好坏均可,但要删去全好边的情况。

初始化对于所有叶子 u u u f u , 0 = 1 , f u , 1 = 0 f_{u,0}=1,f_{u,1}=0 fu,0=1,fu,1=0

然后发现 f u , 0 f_{u,0} fu,0 恒等于 1 1 1,直接合并状态,设 f u f_u fu 表示以 u u u 为根子树内的方案数,那么有:

f u = 1 + ∏ v ( 2 + f v − 1 ) − 1 = ∏ v ( f v + 1 ) f_u=1+\prod_v(2+f_v-1)-1=\prod_v (f_v+1) fu=1+v(2+fv1)1=v(fv+1)

考虑在换根过程中的影响,新根 u u u 子树内的计算不变,原来的根 f a u fa_u fau 子树内计算也不变,唯一有变化的就是贡献计算由 u → f a u \to fa ufa 变为 f a → u fa \to u fau

g u g_u gu 表示以 u u u 为根的方案数,那么答案的变化量 delta \text{delta} delta 即为 f u ( g f a f u + 1 + 1 ) − g f a f_u(\frac{g_{fa}}{f_u+1}+1)-g_{fa} fu(fu+1gfa+1)gfa,即 g u = g f a + delta = f u ( g f a f u + 1 + 1 ) g_u=g_{fa}+\text{delta}=f_u(\frac{g_{fa}}{f_u+1}+1) gu=gfa+delta=fu(fu+1gfa+1)

看似是和平解决了,但还有些问题,比如 f u + 1 f_u+1 fu+1 无逆元怎么办?那就回归式子本身的意义,即只不将 f u + 1 f_u+1 fu+1 乘进答案里,具体地,处理出其所有儿子前缀积后缀积, O ( 1 ) \text{O}(1) O(1) 维护即可。

link

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值