2023暑假牛客多校做题记录

牛客01

C

先忽视操作2不小于1的限制直接计算,发现对每个点会多减掉历史最小值小于0的部分,于是线段树维数历史最小值即可。

E

保序回归,留坑

牛客02

A

J

牛客03

F

图的性质是连边跨度在9以内,考虑如何利用:即在一个点走到另一个点的路径中,任意相邻的9个节点都至少有一个点被访问过;而如果能确定一个必然经过的节点,那就只需要通过预处理这个点到其它点的距离即可算出答案。
考虑分治,每次对区间中间的9个点算出在区间内走,到每个点正反的最短路,左右两边分治下去做。这样在询问时:如果两个点有一个点在中间,肯定没问题;否则如果两个点在左右两边,则路径一定经过中间9个点之一,枚举计算完返回;否则就是都在一边,这时路径有两种可能:一种是会跨到另一边(这就也会经过中间9个点之一),另一种是不跨过(就变成只考虑一边的问题)。

牛客04

D Classical Problem?

队友给出了核心思路:k比较小的时候直接枚举,k较大的时候就只有比较少的位数,结合答案必然在100左右的范围(2,3进制),考虑枚举这几位是多少,然后二分k得到是否有解,但这样的效率会爆炸。
在还剩半小时多的时候想到,其实只要枚举前两位,然后k依旧是可以二分的,因为在最高位上,相邻的k至少差\(k^{p-2}\),这是后面的p-2位不论怎么改变都无法超过的。
代码不难写,但由于二分边界直接用pow函数计算出锅了,最后一直WA;直接把这个边界也加到二分里计算,就不会有问题(以后尽量避免不必要的实数操作!

G Famished Felbat

场上没开,后来看了下感觉能推,但思维僵化了,算贡献直接想整除分块,但每个数分出的块是不同的,难以高效合并!
考虑整除分块的时候,把整除完恰好为x改为整除完至少为x,这样就变成一个简洁的式子,贡献差分一下就是1(经典做法)小于根号的k直接枚举,大于的枚举整除结果,然后分别用BIT和双指针算算就行!

牛客05

牛客06

D

牛客09

F

有一个思路比较顺的DP:按照num一个个考虑,记录当前每个位置是否已填,以及B数组剩余的状态;然后枚举新增的位置,判断合法性转移。容易发现B数组剩余的状态数不多,手模几个情况卡不到100(实际上最多72);瓶颈在于转移,如果直接枚举新增的集合,总复杂度是\(O(72m3^n)\),可以用每次新增一个的方法优化枚举子集,但这样得记录新增的个数以及上一个新增的位置,总复杂度是\(O(72mn^22^n)\),都难以通过。
发现按照上面的思路已经难以优化了,即同时记录72和\(2^n\)过于暴力了!考虑优化这个\(2^n\):我们要记这么多,为的就是满足每个位置恰好只填一个数这个比较严格的限制;能否将其放宽?考虑容斥!由于把num全部考虑完后,总共填了n次,所以只需考虑每个位置都填过或者每个位置被填不超过一次这两个等价表达中的一个,而容斥的话,肯定是对前者容斥更容易,即枚举至少没有被填过的位置集合,问题就变成在一个位置子集内填数,那DP的时候就只要记录72个状态,用组合数算算转移即可!

posted @ 2023-07-19 18:22  sz[sz]  阅读(18)  评论(0编辑  收藏  举报