康复计划
记录一下近期刷过的题,毕竟三年没碰OI了
8月
Luogu1077 & 1095 水题
Luogu3842 一开始想法是对的,结果敲错了一个字母;后来写的大讨论有个地方没有+1
Luogu1541 当前位置的这个状态不需要记录
Luogu4059 不需要记录末尾空格的数量,因为转移的时候与数量无关,只与最后空格的位置有关。(注意上下都是空格的情况不存在)
Luogu1833 二进制拆分,把多重背包中的“数量”用二进制数的和表示
Luogu1064 对取0/1/2个附件的主件讨论,抓化成01背包
Luogu1941 向下y,只能取一次,向上x,可以取无限次。抽象成一个01背包+一个完全背包模型。对高度为m特判一下 踩的坑:1.向上取整(a-1)/b+1
注意极端情况a=0,b=1
,特判掉 2.完全背包本质上就是优化了的多重背包,所以就不要枚举第i个物品取的个数了(因为可以“重复”利用前面得到的结果),直接dp[i][j]=dp[i][j-x[i]]+1
(这是在i这个位置跳了k次->k+1次的情况)和dp[i][j]=dp[i-1][j-x[i]]+1
(这是在i位置跳的第一次的情况)即可。3. 注意本题中“第i个物品不选”对应的是下降y[i],因此要放在跳x[i] k次之后 4. 高度为m之后不能再跳了,判掉这种情况,注意仍然只需要枚举 [m-x[i] .. m]这段(dp[i][m-x[i]..m] & dp[i-1][m-x[i]..m])
Luogu3146 这个题设状态是关键 dp[i][j]表示[i..j]全部合并完成所对应的值(否则为-1),这样的话不用额外记录合并的具体细节(也记录不了),当发现状态记录不了一些事情时,可以添加限制条件方便转移。
Luogu4302 设dp[i][j]为[i..j]折叠的最小长度,转移的时候只需要算一下[i..k]在[k+1..j]中出现了多少次即可
Luogu1063 水题
Luogu4342 注意不仅要记录最大值,还有最小值(因为两个负值乘起来可能更大)。被读入坑惨了。scanf("%d\n",&n)
,不要用getchar()
(或者用两次)
CF149D 区间dp,直接做会有重复,如对于()()()
,在计算dp[1][6]
时,我只需要用dp[1][2] * dp[3][6]
,因为如果我再计算dp[1][4] * dp[5][6]
的话,dp[1][4]
出现的情况都会在dp[1][2] * dp[3][6]
中包含了,导致了重复,所以只需要记录最近的匹配位置match[i]
,每次用dp[i][match[i]] * dp[match[i]+1][j]
UVA12991 见题解
Luogu3052 直接枚举子集 3^n会超时。考虑令dp[S]
表示安排S中的元素所需要的最少电梯数,这显然不足以表示完全状态,记lft[S]
表示最优情况下剩下的最后的电梯剩余容量(如果前面有电梯能再装下,可以通过对应的转移得到),枚举S中未出现的元素i
,只需要考虑能否装下当前元素。别忘了如果不是更优解但是lft[]
更优的情况
Luogu1879 枚举本行和上行状态,状压dp。注意滚动数组需要清空!!
Luogu3959 写了个不太对的dp,虽然能过但是被uoj叉掉了。
Luogu2831 表示打掉内小猪的最少小鸟数,直接枚举转移用的集合/枚举补集的子集是的,不行。考虑维护一个辅助转移,表示包含的抛物线能打掉的小猪集合,转移枚举即可,时间复杂度,可以优化到等我有时间研究一下
CF1704CD 水题&见题解
CF1704E 记没有出度的点为,考虑当时刻,当前的状态一定是有很多溜水,从源头一直不间断流到,这是因为DAG中最长路长度不超过,从源头的一滴水肯定能到达。也就是说此时不存在这种情况:"--->o-->pos"(中途间断),再次解释一下,如果存在,则'o'处在时刻一定没有水,但是根据其上游有水,而且这些水一定能在至多n时刻以内到达'o',这就证明这种情况不存在。分析出来这个性质,我们只需要对前时刻进行暴力模拟,之后的情况就是:源头先断,源头的下游一个接一个断,直接利用拓扑序求出此时所有点的水量,挪到下游(即出边的点)即可。
Luogu2150 见题解
Luogu2657 数位dp模板题,注意把所有状态包括是否有前导零,与上界的关系都作为状态dp,也可以分块打表。
CF1097C 显然一个括号序列的要么是合法的,要么放在左/右边(且如果能放,只能放在一边),开两个桶记录放在左/右边需要的右/左括号值,取min求和即可,注意特判合法的情况
CF1097D 先考虑n为一个质数幂的形式,显然此时用一个dp解决表示已经分了次,指数数为的概率,转移显然。n可以分解成数个质数幂相乘的形式,而显然不同质数幂之间的选择是独立的,根据E(XY)=E(X)E(Y),对每个质因数单独统计期望,最后相乘即可
Luogu4124 数位dp,把限制条件都作为状态扔到dp数组里即可。注意只需要统计符合要求的方案数即可。
CF1716C 辣鸡题,等我有心情了再写写 UPD8.14 看了2h,还是有点迷..
CF1716D 设表示第轮走到位置的方案数,转移:注意第一位只有种,于是直接转移的复杂度是。然后发现对于同一个,是相同的,可以类比前缀和优化的思想,枚举每个时先统计一下“前缀和”,转移时对于一个可以转移,时间复杂度。统计答案时对于每个分别统计即可,因为“路径”到达的步数可以任意。
CF1712 见题解
Luogu3372&3373 线段树基础操作,注意先乘后加。终于理解含义了!如 变成,懒标记2个,为加和乘,区间乘的时候要把加的lazyadd也乘,相当于是(a[i]+2)3 = a[i]3+23,往下push的时候lazymul管a[i]3,lazyadd管2*3
BZOJ3211 没有修改,开根至多6次,记一下最大值,如果这个区间内最大值<=1就不用开根了,否则O(logn)遍历到叶子再修改
NCPC2018A 记表示能承载总重为的青蛙的最高高度,按大小从大往小遍历,如果就说明能跳出去,然后转移是,因为显然最优的跳法是先让w小的青蛙跳,因此如果能跳出去(这是建立在比中的青蛙当垫脚石的基础上),那么其按最优解跳时一定能跳出去。
CF1702D1 设表示以作为结尾的最长子序列长度,显然直接枚举转移是的,考虑优化。注意到有,所以使得最多少了200,当然为了直观可以取256,同理使最多能多256,因此j只需要从i-512开始枚举即可。注意多组数据注意memset可能会导致超时!
CF1715C 差分一下求出差分数组,考虑g(l..r)的答案:(先排除的情况)即为,算出第个位置被加的次数是,然后维护整个数组的和即可。本sb写了树状数组真是数据结构学傻了
CF1715D 一眼按位独立计算,有一种很精妙的实现:设读入为u,v,w,设u<v,每次如果w该位不为0g[v].push_back(u)
,这样先去掉w该位为0(两个数显然该位都为0),剩余全是两个数该位至少一个1的情况,这样“倒序”的处理的好处就是,每次取,再遍历,比如当前节点为,则这对一定是最后一次遍历,这样决定谁取1就很轻松了,不用像我一开始实现用的“正序”处理先考虑,再对标记,很难写且容易错。这样做也能避免一种情况:中已经有其中一个确定,显然另外一个也可以确定,但是这样的话后面如果已经确定了,前面也可能出现中已经有一个确定的情况,但是这种情况无法维护!用这样的方法,每次取到的都是最后一次取到,就可以完全确定了。
CF1200E 维护答案串的hash值,每次加新串的时候暴力判断最远的hash相等的位置在哪,然后合并。时间复杂度,注意写自然溢出会被卡
Luogu7521 枚举,取模后排序,将分成或者<的情况。>时显然取最大的两项(因为此时答案即为两项之和减去),<时枚举,由于单调性可以直接二分(upper_bound)求出的最大值在哪。时间复杂度。我们可以从大往小枚举,如果当前已经小于ans直接break。时间复杂度玄学。
CF126B 显然满足前后缀相同条件只需要不断跳即可。对于每次跳,再暴力判断是否存在满足当前nxt值的。如果存在直接break。时间复杂度玄学
CF27E 小的几项打表,大的就把质因数分解之后每个因数派发给从小到大的质数即可。
UVA11526 & Luogu2261 数论分块。
Luogu1309 直接每次排序会超时。注意到胜者和负者的相对顺序不会改变,利用归并排序的思想可以做到O(n)合并
Luogu1310 见题解
CF510D 利用map优化dp(去除无用状态)
9月
Luogu2054 打表可以发现答案即为 ,注意不能直接乘方,因为不互质(是由费马小定理推出来的),可以用扩欧求出。我写了原根求出周期,但是没有必要。注意要写快速乘。
ARC146 ABC 见题解 D咕了
UVA11327 求欧拉函数的前缀和,二分一下即可
Luogu3201 见题解
ZROI490 注意f(x)最大是81*18,枚举一下f(x)暴力判断x是否符合条件即可
ZROI491 树形dp,设表示当前结点和均不联通/连通/连通的最小代价,转移dfs即可,注意需强制和连通,标程貌似没有考虑到这一点。
Luogu2014 有依赖的树形背包,类似背包做法,设一个超级根节点(0),每次循环重量(选课数)的时候从2开始而非1,处理一下选课数为 0 的情况即可。
Luogu3803 分治FFT
Luogu2602 数位dp
Luogu2016 树形dp,看错题意了也真是离谱
ARC100 见题解
ZROJ987 一个关键结论:两条链相交当且仅当一条链两个端点的lca在另一条链上。于是问题就变成了树上单点加,求链和(再减1因为自己也包含进去了)。可以用差分/树剖解决。注意最后还需要减去重复的情况,因为如果多条链端点的lca相同(比如说有条),直接统计的结果为,但该部分的答案应为,需要减去一个才可。另外一种考虑是链的性质:点数-边数=1,所以也可以转化为链加(点&边都要维护)链求和
CF739B 考虑枚举被控制点,那些点能控制它,显然单调,我们可以二分祖先的位置,判断是否能控制,问题转化为一个链加单点求和,差分解决,时间复杂度两个log(二分+倍增求出祖先)
Luogu1038 拓扑排序之后模拟即可
10月
CF1738D 可以先写个根据a构造b的程序,发现有规律,略证之后就可以写了。首先,如果有很多个,那么a中的情况一定是这样:,而对于yi来说,我们只关注是否存在,找到这样的yi之后将其放在y序列的末尾,剩下的可以随便排。实际上就是把a分成了若干块,x || y1 y2 .. yi || z..,每块与k的大小关系都是与前面相反。利用反证法以及b的定义可以说明一定只存在一个yi。至于算k,统计一下<=k的块的大小之和即可
Luogu2152 辗转相除+高精,利用 /2 加速,压位加速
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示