康复计划

记录一下近期刷过的题,毕竟三年没碰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 \(dp[S]\)表示打掉\(S\)内小猪的最少小鸟数,直接枚举转移用的集合/枚举补集的子集是\(4^n/3^n\)的,不行。考虑维护一个\(lin[i][j]\)辅助转移,表示包含\(i 、j\)的抛物线能打掉的小猪集合,转移枚举\(i\)\(j\)即可,时间复杂度\(n^2*2^n\),可以优化到\(2^n*n\)等我有时间研究一下

CF1704CD 水题&见题解

CF1704E 记没有出度的点为\(pos\),考虑当时刻\(t\geq n\),当前的状态一定是有很多溜水,从源头一直不间断流到\(pos\),这是因为DAG中最长路长度不超过\(n\),从源头的一滴水肯定能到达\(pos\)。也就是说此时不存在这种情况:"--->o-->pos"(中途间断),再次解释一下,如果存在,则'o'处在\(t-1\)时刻一定没有水,但是根据其上游有水,而且这些水一定能在至多n时刻以内到达'o',这就证明这种情况不存在。分析出来这个性质,我们只需要对前\(n\)时刻进行暴力模拟,之后的情况就是:源头先断,源头的下游一个接一个断,直接利用拓扑序求出此时所有点的水量,挪到下游(即出边的点)即可。

Luogu2150 见题解

Luogu2657 数位dp模板题,注意把所有状态包括是否有前导零,与上界的关系都作为状态dp,也可以分块打表。

CF1097C 显然一个括号序列的要么是合法的,要么放在左/右边(且如果能放,只能放在一边),开两个桶记录放在左/右边需要的右/左括号值,取min求和即可,注意特判合法的情况

CF1097D 先考虑n为一个质数幂的形式,显然此时用一个dp解决\(dp[i][j]\)表示已经分了\(i\)次,指数数为\(j\)的概率,转移显然。n可以分解成数个质数幂相乘的形式,而显然不同质数幂之间的选择是独立的,根据E(XY)=E(X)E(Y),对每个质因数单独统计期望,最后相乘即可

Luogu4124 数位dp,把限制条件都作为状态扔到dp数组里即可。注意只需要统计符合要求的方案数即可。

CF1716C 辣鸡题,等我有心情了再写写 UPD8.14 看了2h,还是有点迷..

CF1716D 设\(dp[i][j]\)表示第\(i\)轮走到\(j\)位置的方案数,转移:$$dp[i][j] = \Sigma_{num=1}^{j-num*(k+i-1)\geq 0} dp[i-1][j-num * (k+i-1)]$$注意第一位只有\(\sqrt{n}\)种,于是直接转移的复杂度是\(O(n^2\sqrt{n})\)。然后发现对于同一个\(i\)\(k+i-1\)是相同的,可以类比前缀和优化的思想,枚举每个\(i\)时先统计一下“前缀和”\(pre[j]=pre[j-(k+i-1)]+dp[i][j]\),转移时对于一个\(i,j\)可以\(O(1)\)转移,时间复杂度\(O(n^2\sqrt{n})\)。统计答案时对于每个\(i\)分别统计\(dp[i][j]\)即可,因为“路径”到达的步数可以任意。

CF1712 见题解

Luogu3372&3373 线段树基础操作,注意先乘后加。终于理解含义了!如\(a[l..r]+2, a[l..r]*3, a[l..r]+4\) 变成\(a[l..r].sum+2 *3 +4\),懒标记2个,为加和乘,区间乘的时候要把加的lazyadd也乘,相当于是(a[i]+2)3 = a[i]3+23,往下push的时候lazymul管a[i]3,lazyadd管2*3

BZOJ3211 没有修改,开根至多6次,记一下最大值,如果这个区间内最大值<=1就不用开根了,否则O(logn)遍历到叶子再修改

NCPC2018A 记\(f[W]\)表示能承载总重为\(W\)的青蛙的最高高度,按\(w_i\)大小从大往小遍历,如果\(f[w_i]+l[i]>d\)就说明\(i\)能跳出去,然后转移是\(f[w_i]=min{f[w_i+s]+h_i}\),因为显然最优的跳法是先让w小的青蛙跳,因此如果\(i\)能跳出去(这是建立在比\(i\)中的青蛙当垫脚石的基础上),那么其按最优解跳时一定能跳出去。

CF1702D1 设\(dp[i]\)表示以\(i\)作为结尾的最长子序列长度,显然直接枚举转移是\(O(n^2)\)的,考虑优化。注意到有\(a_i\leq 200\),所以\(a_j \bigoplus i\)使得\(i\)最多少了200,当然为了直观可以取256,同理\(a_j \bigoplus i\)使\(i\)最多能多256,因此j只需要从i-512开始枚举即可。注意多组数据注意memset可能会导致超时!

CF1715C 差分一下求出差分数组\(a[2..n]\),考虑g(l..r)的答案:(先排除\(l==r\)的情况)即为\(a[l+1..r]+1\),算出第\(i\)个位置被加的次数是\((n-i+1)*(i-1)\),然后维护整个数组的和即可。本sb写了树状数组真是数据结构学傻了

CF1715D 一眼按位独立计算,有一种很精妙的实现:设读入为u,v,w,设u<v,每次如果w该位不为0g[v].push_back(u),这样先去掉w该位为0(两个数显然该位都为0),剩余全是两个数该位至少一个1的情况,这样“倒序”的处理的好处就是,每次取\(i\),再遍历\(g[i]\),比如当前节点为\(u\),则\((u,i)\)这对一定是最后一次遍历,这样决定谁取1就很轻松了,不用像我一开始实现用的“正序”处理先考虑\(i\),再对\(u\)标记,很难写且容易错。这样做也能避免一种情况:\((i,j)\)中已经有其中一个确定,显然另外一个也可以确定,但是这样的话后面如果已经确定了,前面也可能出现\((i,j)\)中已经有一个确定的情况,但是这种情况无法维护!用这样的方法,每次取到的\((u,i)\)都是最后一次取到,就可以完全确定了。

CF1200E 维护答案串的hash值,每次加新串的时候暴力判断最远的hash相等的位置在哪,然后合并。时间复杂度\(O(\Sigma n)\),注意写自然溢出会被卡

Luogu7521 枚举\(a_k\),取模后排序,将\(i,j\)分成\(a_i+a_j>a_k\)或者<的情况。>时显然取最大的两项(因为此时答案即为两项之和减去\(a_k\)),<时枚举\(a_i\),由于单调性可以直接二分(upper_bound)求出\(<a_k-a_i-1\)的最大值在哪。时间复杂度\(O(n^2logn)\)。我们可以从大往小枚举\(a_k\),如果当前\(a_k\)已经小于ans直接break。时间复杂度玄学。

CF126B 显然满足前后缀相同条件只需要不断跳\(nxt[n]\)即可。对于每次跳,再暴力判断是否存在\(nxt_i(i=2..n-1)\)满足当前nxt值的。如果存在直接break。时间复杂度玄学

CF27E 小的几项打表,大的就把\(n\)质因数分解之后每个因数派发给从小到大的质数即可。

UVA11526 & Luogu2261 数论分块。

Luogu1309 直接每次排序会超时。注意到胜者和负者的相对顺序不会改变,利用归并排序的思想可以做到O(n)合并

Luogu1310 见题解

CF510D 利用map优化dp(去除无用状态)

9月

Luogu2054 打表可以发现答案即为 \(L*inv(2^{m}) \mod n+1\),注意不能直接乘方\((n+1-2)\),因为不互质(是由费马小定理推出来的),可以用扩欧求出\(ax=1(\mod b) \rightarrow ax+by=1\)。我写了原根求出周期,但是没有必要。注意要写快速乘。

ARC146 ABC 见题解 D咕了

UVA11327 求欧拉函数的前缀和,二分一下即可

Luogu3201 见题解

ZROI490 注意f(x)最大是81*18,枚举一下f(x)暴力判断x是否符合条件即可

ZROI491 树形dp,设\(dp[i][0/1/2]\)表示当前结点和\(XY\)均不联通/\(X\)连通/\(Y\)连通的最小代价,转移dfs即可,注意\(dp[u][1/2]\)需强制和\(X/Y\)连通,标程貌似没有考虑到这一点。

Luogu2014 有依赖的树形背包,类似背包做法,设一个超级根节点(0),每次循环重量(选课数)的时候从2开始而非1,处理一下选课数为 0 的情况即可。

Luogu3803 分治FFT

Luogu2602 数位dp

Luogu2016 树形dp,看错题意了也真是离谱

ARC100 见题解

ZROJ987 一个关键结论:两条链相交当且仅当一条链两个端点的lca在另一条链上。于是问题就变成了树上单点加,求链和(再减1因为自己也包含进去了)。可以用差分/树剖解决。注意最后还需要减去重复的情况,因为如果多条链端点的lca相同(比如说有\(a\)条),直接统计的结果为\((a-1)*a\),但该部分的答案应为\((a-1)*a / 2\),需要减去一个\((a-1)*a/2\)才可。另外一种考虑是链的性质:点数-边数=1,所以也可以转化为链加(点&边都要维护)链求和

CF739B 考虑枚举被控制点,那些点能控制它,\(dis\)显然单调,我们可以二分祖先的位置,判断是否能控制,问题转化为一个链加单点求和,差分解决,时间复杂度两个log(二分+倍增求出祖先)

Luogu1038 拓扑排序之后模拟即可

10月
CF1738D 可以先写个根据a构造b的程序,发现有规律,略证之后就可以写了。首先,如果有很多个\(b_y=x\),那么a中的情况一定是这样:\(x y1 y2 ..\),而对于yi来说,我们只关注是否存在\(b_z=yi\),找到这样的yi之后将其放在y序列的末尾,剩下的可以随便排。实际上就是把a分成了若干块,x || y1 y2 .. yi || z..,每块与k的大小关系都是与前面相反。利用反证法以及b的定义可以说明一定只存在一个yi。至于算k,统计一下<=k的块的大小之和即可

Luogu2152 辗转相除+高精,利用 /2 加速,压位加速

posted @ 2022-08-08 01:12  SkyRainWind  阅读(38)  评论(0编辑  收藏  举报