ABC 384(A~F)

期末周的第二把网瘾,vp了一把abc。这把打得还是比较舒服的,做出了A~E。但最后两道题还是出得太慢了(一道思路太慢,一道调试太慢)。什么时候能够在赛时做出F题呢qwq...

ABC

这场abc的ABC题还是很白给的,就不再赘述了。

D

前缀后缀和 + 二分

题意是给定一个循环数组和定值sum,问是否存在一个子数组,使得总和恰为sum

这个子数组的形式只有两种情况:

  1. 原数组的某个子区间
  2. 原数组某个后缀 + 若干个整个数组 + 原数组某个前缀 拼接而成

对于情况1,采用枚举右端点,二分左端点的传统套路
对于情况2,设后缀和为suf,前缀和为pre , 则有:

pre + k * S + suf == sum

其中S为整个数组的所有元素和

暴力枚举presuf的复杂度是O(n2)的,考虑优化:

枚举suf,由于pre <= S , 因此可以将这个式子中的pre看做余数,k看做商。则一定有 : (sumsuf) % S == pre 。这样问题就转化为找一个和为(sumsuf) % S的前缀。直接二分找即可,类似情况1。

两种情况的复杂度均为O(nlogn)

刚开始时看这道题就有了这个思路,但到比赛快结束时才AC。还是太菜了。。。

code

E

优先队列版bfs

思路一点都不难想,就是每次扩展时选择可以扩展的所有位置中最小的那个数就行。

因为每一次对于当前可以选择的所有数,选择了某个数时,只会扩大选择范围,而原来可以选择的那些数都仍然可以被选。而越小的数越可以选择。顺着这样的思路,很容易想到每次贪心取最小就是正解。

实现也很简单,直接队列改为小根堆再bfs就行了。

不过赛时此题WA了三发。debug了半天最后才发现是地图中的数据也会爆longlong,而地图的数据类型一直都是int(悲。。

code

F

数学题。赛后看完官方题解后思路逐渐清晰,最后自己补出来了。

题意就是给一个数组,求出数组中每一对 (Ai,Aj) 之和并除去其中所有的因子2 的总和,注意(Ai,Ai)也算一对数

由于最大值Ai+Aj <= 2107 , 故除以2kk很小,不会超过26.因此考虑找到 对于一个特定的k , 恰好含有k个因子2的所有Ai+Aj , 并设它们的总和为res[k]

则:

 ans = Σ (res[k] / 2^k) , k = 0,1,2 …… 25

res[k]可以利用前缀和的思想来计算:

sum[k]:所有能被2k整除的Ai+Aj的总和

则恰好含有k个因子2 的Ai+Aj的总和res[k]为 :

 res[k] = sum[k] - sum[k + 1]

现在考虑计算所有的sum[k]:

暴力即直接O(n2)找每一对数的和,并判断是否为2k的倍数即可。优化可以利用余数的性质来优化:

  • 对于任意两个数x,y,它们除以2k的余数为rx,ry。若二者的和是2k的倍数,则一定是以下两种情况之一:
    1. rx,ry均为0
    2. rx+ry=2k

因此可以考虑O(n)遍历数组,用map记录所有数除以2k后得到的余数r的 个数 和 对应原数的总和 。

对于某个余数r,它可以和余数为2kr的信息配对(相加后一定是2k的倍数)。直接数学计算出它们产生的贡献即可,最后把所有贡献累加起来。

注意当余数为02k1时需要特判,因为要找的对应余数的信息就是本身。

code

G

G看官方题解是个分块,不太会qwq...那就补到这里吧。

posted @   jxs123  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示
主题色彩