2023-2024学年上做题记录
2023-2024学年上做题记录
2023-10-22
P1896 (互不侵犯)
由于状压 \(dp\) 实在是太菜了,做一下来来练练手
大概意思就是给你一个 \(n \times n\) 的棋盘和 \(k\) 个棋子,求使得这些棋子周围八个格子里没有其他棋子的摆放方案数。
一看范围很小,很适合状压,考虑状态设计。
设 \(f_{i, j, k}\) 表示在第 \(i\) 行,状态为 \(j\)(\(j\) 是一个二进制数,表示那些格子放棋子),目前一共用了 \(k\) 个棋子。
首先考虑对单独的 \(j\) 的限制。
就一行而言,只需要满足没有左右相邻的即可,所以判断条件为 \(j\) 与 \(j\) 左移或右移一位是否为零。因为如果左移或右移后与上原来的状态为一就代表有相邻的棋子,不满足条件。而对于每一种状态,也需要求出需要多少棋子,也就是在二进制的情况下有多少位是 \(1\)。判断这一位是否为一只用将原状态与上 \(1\) 左移位数即可。
考虑转移。
从上到下转移,枚举相邻两行的状态,判断是否合法即可。判断条件也简单上一行与上这一行的原状态,左移一位的状态,右移一位的状态即可,原理与上面的差不多,这里不过多赘述。
上面的状态可以预处理出来,后面转移直接用即可。
P9753 [CSP-S 2023] 消消乐
大概的意思就是两个相邻且相同的字母可以消除,问一个字符串有多少个子串可以全部删除。
\(Subtask_{1-2}\)
枚举左右区间,暴力判断即可。
\(Subtask_3\)
使用栈维护即可,和括号序列差不多的。
\(Subtask_{4-7}\)
根据 \(Subtask_3\) 的思路,想到如果多加一个可以消除的最小的子串,也就是 \(s_i = s_{i + 1}\) 时,会对之前的子串产生什么影响。
如果这个子串能和之前的合法子串接上,那么其贡献就是接上的合法子串的贡献加上自己的贡献。
既然如此,考虑 \(dp\),记 \(f_i\) 表示以第 \(i\) 个字符为结尾的合法子串的方案数,最终答案为 \(\sum f_i\) ,考虑 \(f_i\) 的转移。
根据之前分析的贡献可以发现,只需要知道在之前子串是否有贡献,以及在此之前的与当前字母相同的最近位置即可。记在之前与当前字母相同的最近位置为 \(fa_i\),由于只有 \(26\) 个字母,那么如果每次暴力向前跳找与自己相同二点字母只会找 \(26\) 次,这是完全可以接受的。而此时的 \(f\) 的转移为 \(f_i = f_{fa_i - 1} + 1\) 。
时间复杂度 \(O(26n)\)。
2023-10-23
P3389[模板高斯消元法]
就高斯消元,用来解决线性方程组,初中数学知识。
和二元一次方程组消元过程差不多,只是一个拓展而已,这里就不作过多赘述。
注意下 \(No\) \(solution\) 的情况,在一个元的所有系数全部为 \(0\) 时,其要么无解,要么多解。
P2455 [SDOI2006] 线性方程组
这个注意判无解和多解,在上一个模板题判 \(No\) \(solution\) 的情况下,在右边系数为零,左边系数不为零时无解,两边均为零时多解。
同时还需要注意消元的顺序,有时消元顺序会影响有无解的判断,所以在消元时应该整体扫描选取有用的。
2023-10-24
P4343 [SHOI2015] 自动刷题机
链接都放这里了,就不再过多讲述题面了。
可以发现如果 \(n\) 变大,那么通过的题目数量就会变小,\(n\) 变大,通过题目的数量就会增多,所以,答案具有单调性,可以二分。
二分答案后 \(check\) 时直接模拟判断过了多少道题即可。
求最大最小满足题意的答案只需要判断一下左右边界即可。
这样就做完了,时间复杂度 \(O(n\log n)\) 。
P1314 [NOIP2011 提高组] 聪明的质监员
链接都放这里了,就不再过多讲述题面了。
发现 \(W\) 变大答案变小,\(W\) 变小答案变大。明显的单调性,开始二分。
二分答案时容易的,如何快速求和呢?
由于有多个区间和相乘,考虑前缀和,然后直接乘即可。
这样就做完了,时间复杂度 \(O(n\log n)\)。
CF19B Checkout Assistant
意思是你有 \(n\) 个物品,每个物品有检查时间为 \(t_i\),代价为 \(c_i\),检查后物品可拿走。同时在这 \(t_i\) 的时间里,你可以拿走其他 \(t_i\) 个物品。问要拿走 \(n\) 个物品需要付出的最小代价是多少。
可以想到,为了保证答案最有,那么在一个物品检查的 \(t_i\) 时间里,每个时间都会拿走一个物品,加上这个物品本身,那么在这 \(t_i\) 个时间里可以拿到 \(t_i + 1\) 个物品,代价为 \(c_i\)。
那么现在就问题就转变成了一个 \(01\) 背包的问题。
现在已知每个物品的代价,占用空间,但还不知道背包容量,所以再来考虑背包容量的问题。
首先需要拿 \(n\) 个物品,然后又因为可能在拿最后一个物品时,其他的物品都已经拿完了,所以在这个物品对应的 \(t_i\) 时间里只会拿到这一个物品,所以背包的最大容量应该时 \(n + max(f_i)\)。
接着跑一下 \(01\) 背包即可。
CF9D How many trees?
题意:用n个点组成二叉树,问高度大于等于h的有多少个。(不得不说,翻译是真的精简。)
计数题,这很 \(DP\)。
记 \(f_{i, j}\) 表示由 \(i\) 个点组成,高度不超过 \(j\) 的二叉树有多少个。
那么最后的答案就是 \(f_{n, n} - f_{n, j - 1}\) (\(n\) 个点高度最多为 \(n\))。
考虑转移。
假设 \(k\) 表示当前节点左子树的数量,那么右子树的数量就为 \(n - i - 1\),减一是因为要剪掉根节点。
那么可以得到转移如下:
时间复杂度 \(O(n^3)\),可以通过本题。
CF10D LCIS
题意:求两个串的最长公共上升子序列。(太精简了捏。)
首先,在求最长上升子序列时,是记录了一个末尾 \(b_i\) 的最长上升子序列的数量。
然后,在求最长公共子序列时,是记录了一个 \(f_{i, j}\) 表示从 \(a\) 的前 \(i\) 个与 \(b\) 的前 \(j\) 个选出的最长公共子序列。
整合一下可以及 \(f_{i, j}\) 表示在 \(a\) 的前 \(i\) 个数中,结尾为 \(b_j\) 的最长公共上升子序列的长度。
枚举 \(i, j\) 后进行分类讨论:
- \(a_i \not= b_j\) ,直接转移 \(f_{i, j} = f_{i - 1, j}\) 因为 \(j\) 是必选的,所以 \(j\) 不能改变。
- \(a_i = b_j\) ,可以枚举之前的结尾,尝试把 \(b_j\) 加入,所以 \(f_{i, j} = \max_{b_k < b_j}f_{i - 1, k} + 1 (1 \le k \le n)\)。
时间复杂度 \(O(n ^ 3)\),虽然有 \(O(n ^ 2)\) 做法,但 \(O(n^3)\) 就够了。
CF11D A Simple Task
题意:求简单无向图的环数。
看一眼数据范围 \(1 \le n \le 19\) 这很状压。
可以状态压缩每次走到的路径,记录这 \(n\) 个点中有哪些点走过,哪些点没有走过。
但会发现,形如 \(1, 3, 2\) 这样的环还会因 \(3, 2, 1\) 被计算一次,所以考虑如何去重。可以钦定状压的第一个位置是这个环中的最小的点,那么这样就可以避免重复了。
设 \(f_{k, i}\) 表示考虑到前 \(i\) 个点,状态为 \(k\)。
可以枚举与 \(i\) 相连的点 \(j\) 进行转移:
如果 \(j\) 比当前状态的最小值更小,不满足条件,不转移、
如果 \(j\) 在没有经历过,之间转移为:\(f_{k | (1 << j),j} += f_{k, i}\)。
如果 \(j\) 在之前被经历过且是起点,那么 \(ans += f_{k, i}\)。
如果 \(j\) 在之前被经历过但不是起点,不用考虑转移。
由于双向建边会导致计算二元环,所以 \(ans -= m\)。
同时每个环会被顺时针和逆时针各计算一次,所以 \(ans \div= 2\)。
最后由于状态压缩如果点的标号从 \(1\) 开始会出现一些问题,导致有的东西没有算到,所以点的标号应该从 \(0\) 开始。
CF599C Gerld and Giant Chess
题意:给定一个 \(h \times w\) 的棋盘,棋盘上只有 \(n\) 个格子是黑色的,其他格子都是白色的。在棋盘左上角有一个卒,每一步可以向右或者向下移动一格,并且不能移动到黑色格子中。求这个卒从左上角移动到右下角,一共有多少种可能的路线。
看到题目,感觉这很 \(dp\),但由于 \(h, w\) 的范围太大,所以考虑从黑点入手。
设 \(f_{i}\) 表示从原点到第 \(i\) 个黑点路上不经过其他黑点的方案数,这个看似与最后答案无关,但可以假设最后一个终点为最后一个黑点,那么答案就为 \(f_n\)。
考虑转移。
发现直接计算路径显然是不现实的,可以考虑进行容斥。
如果在不考虑不经过其他黑点的情况下,\(f_i = C_{x_i + y_i - 2} ^ {x_i - 1}\) ,从原点到当前点一共需要走 \(x_i + y_i - 2\) 步,其中需要选择 \(x_i - 1\) 步进行向右的操作。
再记一个 \(g_{i, j}\) 表示从第 \(i\) 个黑点到第 \(j\) 个黑点所有路径的方案。所以就有 \(g_{i, j} = C_{x_i + y_i - x_j - y_j} ^ {x _ i - x_j}\) 因为一共需要走 \(x_i + y_i - x_j - y_j\),需要选择 \(x _ i - x_j\) 步走向右的操作。
所以转移为:
时间复杂度 \(O(n ^ 2)\)。
2023-10-26
P4097 【模板】李超线段树 / [HEOI2013] Segment
李超线段树版题,详见学习笔记 算法学习笔记:线段树进阶
P4254 [JSOI2008] Blue Mary 开公司
也是李超线段树的版题,甚至是直线,不过只是动态插入及查询。这个李超线段树是完全支持的。
2023-10-27
P4556 [Vani有约会] 雨天的尾巴 /【模板】线段树合并
线段树合并版题,详见学习笔记 算法学习笔记:线段树进阶
2023-10-28
P8844 [传智杯 #4 初赛] 小卡与落叶
虽然我知道这道题有不用线段树合并的方法,但为了练习线段树合并,仍选择线段树合并写法。
首先注意到修改操作是先把整棵树染成绿色,再把深度大于等于 \(x\) 的点染成黄色。
那么对于每次询问,需要记录在此之前的最后一个染色操作的深度(下文称为查询对应的修改)即可,查询就变成了查找 \(x\) 子树中,深度该次查找对应修改深度的子树和。
首先可以想到一个对于每次询问 \(O(n)\) 查找的方法,但这会超时,换个方向考虑。
发现每次查询与查询对应的修改之间互不干扰,所以考虑离线处理。
考虑把每次操作离线下来,按照查询的深度排序,那么就可以从下往上依次更新。
由于每个查询对应的修改深度不同,所以考虑使用线段树维护每个节点的深度,然后依次向上合并,对于每次询问查询使用线段树查询深度大于对应修改的深度即可。也就是查询对应修改深度到深度 \(n\) 中的节点,也就是线段树的区间查询。
2023-10-30
P1535 [USACO08MAR] Cow Travelling S
一个小清新的记忆化搜索。
暴力的搜索很简单,每次走四个方向即可。
这时就会发现,对于一些位置会重复经过,这就大大提升了搜索的时间复杂度。
考虑想 \(dp\) 那样用数组记录在某个部分的解,后续再遇到的时候就可以直接拿出来用了。
这就是记忆化搜索。
对于本题而言,可以记一个 \(f_{x, y, t}\) 表示需要 \(t\) 个时间从坐标 \(x, y\) 到目标地点的路径数量是多少。
然后跑一下记搜即可。
P1434 [SHOI2002] 滑雪
同样的小清新记搜。
记 \(f_{x, y}\) 表示从 \(f_{x, y}\) 开始的最长滑雪路线。
根据这个跑一下记搜即可。
P1352 没有上司的舞会
一个小清新树形 \(dp\)。
记 \(f_{i, 0}\) 表示以不选 \(i\) 时 \(i\) 子树中的最大快乐值,\(f_{i, 1}\) 表示选 \(i\) 时 \(i\) 子树中的最大快乐值,\(son_i\) 表示 \(i\) 儿子节点集合。
则有如下转移:
然后只需要找一下根节点即可。由于是有向边,入度为 \(0\) 的就是根节点。
2023-10-31
P1390 公约数的和
给定 \(n\), 求
先让 \(j\) 从 \(1\) 开始,最后剪掉重复计算部分即可。
那么,式子,启动 。
记 \(D = de\):
预处理一下 \(\phi\) 的前缀和,套个整除分块即可。
P2257 YY的GCD
题意:
可以枚举 \(D\),预处理后面的东西。具体来说就是用欧拉筛筛完质数和 \(\mu\) 过后枚举每个质数的 \(x\) 倍,倍数的答案加上 \(\mu(x)\) 即可。
在求个前缀和,整除分块搞一下即可。
P3810 【模板】三维偏序(陌上花开)
等后面的 \(CDQ\) 学习笔记吧。
P3195 [HNOI2008] 玩具装箱
首先写出一个 \(O(n ^ 2)\) 的简单 \(dp\)。
记 \(dp_i\) 表示收纳前 \(i\) 个玩具需要的最小花费,\(sum_i\) 表示 \(C_i\) 的前缀和,那就可以得到如下转移:
由于我不想证明决策单调性,所以这里就不写了,写一下推式子的过程吧。
这里记 \(f_i = sum_i + 1, L = L + 1\)。(主要方便后面化简)
假设有 \(k > j\) 且决策点 \(k\) 比决策点 \(j\) 优
也就是说只要满足 \(k > j\) 且满足上述条件,那么用更新 \(k\) 一定比 \(j\) 优,拿个单调队列维护即可。
P3628 [APIO2010] 特别行动队
先写出一个 \(O(n ^ 2)\) 的简单 \(dp\)。
这里记 \(dp_i\) 表示选前 \(i\) 个人,战力最大是多少,\(sum_i\) 是 \(x_i\) 的前缀和,得到如下转移:
假设有 \(k > j\) 且决策点 \(k\) 比决策点 \(j\) 优:
也就是说只要满足 \(k > j\) 且满足上述条件,那么用更新 \(k\) 一定比 \(j\) 优,拿个单调队列维护即可。
2023-11-1
P2900 [USACO08MAR] Land Acquisition G
考虑如何避免求区间最大值。
可以先将土地按照 \(w\) 从大到小排序,那么可以发现,如果一块土地会有单独贡献 \(w, l\) 一定不会被另一块土地的 \(w, l\) 完全包含。
也就是说,如果按照 \(w\) 从大到小排序,如果后面的某块土地的 \(l\) 值小于前面的土地,那么这块土地一定不会做出贡献,就把其去掉。
这个很好维护,拿个栈跑一下即可。那么现在就得到了一个 \(w\) 单调递减,\(l\) 单调递增的序列了。
可以写出一个 \(O(n ^ 2)\) 的 \(dp\),记 \(dp_i\) 表示购买前 \(i\) 块土地的最小代价,得到转移:
假设有 \(k > j\) 且决策点 \(k\) 比决策点 \(j\) 优:
也就是说只要满足 \(k > j\) 且满足上述条件,那么用更新 \(k\) 一定比 \(j\) 优,拿个单调队列维护即可。
P2522 [HAOI2011] Problem b
给定 \(a, b, c, d, k\),求:
先不管是从 \(a, b\) 开始枚举的,这个后面容斥掉即可,那么式子就成了:
前缀和预处理 \(\mu\),跑整除分块即可算出答案。
最后容斥一下,记算上面那个式子为 \(f_{i, j}\):
这样就做完了。
P2158 [SDOI2008] 仪仗队
由于能被看到一定是在中间没有经过任何的其他点,所以能被看到的点的 \(x, y\) 互质。
又因为给定的 \(n\) 是点的个数,需要求的互质是以边来看的,所以应该是 \(n - 1\) 范围以内的。
所以的答案为:
现在就有了两种做法,一种拿莫反跑,一种拿欧拉函数跑。由于我第一次推的式子是莫反的,所以这里说莫反吧。
开始推式子:
虽然 \(O(n)\) 可做,但还可以优化一下。
对 \(\mu\) 做个前缀和,拿整除分块跑一下就有 \(O(\sqrt n)\)。
需要注意的是由于是从 \(1\) 到 \(n - 1\),最边上的两个点不会被算到,所以要 \(+2\)。
还有就是当 \(n = 1\) 时,\(C\) 君已经占满了,所以应该输出 \(0\),程序由于有 \(+2\) 所以会有问题,特判一下即可。
P5785 任务安排
先来看一道弱化版:P2365 任务安排
这道题的数据范围较小,而且 \(0 \le t_i\) ,比较好做。
先写一个 \(O(n ^ 2)\) 做法。
记 \(dp_i\) 表示前 \(i\) 个物品需要的最小时间,\(sumc_i\) 表示 \(c_i\) 的前缀和,\(sumt_i\) 表示 \(t_i\) 的前缀和。
可以得到如下转移:
这样就可以过掉 \(P2356\)。
考虑优化。
假设有 \(k > j\) 且决策点 \(k\) 比决策点 \(j\) 优:
你认为这样再上个优先队列就完了?
\(no,no,no\) 再仔细地读一下题你会发现 \(t_i\) 有可能会小于 \(0\)。这就意味着 \(sumt\) 不在是一个单调的序列了。
那这该怎么办呢?
由于 \(sumt\) 并不单调,所以这就意味着不能通过判断相邻两点的关系来弹出队头了。
但队尾的比较并不影响,所以就变成了一个单调栈。
至于查找最优决策点,二分一下即可。时间复杂度 \(O(n ^ 2)\)。
P3327 [SDOI2015] 约数个数和
给定 \(n, m\),求:
首先需要知道 (我也不知道怎么证的,背就完了)
记 \(f_x = \sum_{i = 1} ^ x \left \lfloor \frac{x}{i} \right \rfloor\),由于 \(\left \lfloor \frac{n}{xd} \right \rfloor = \frac{\frac{n}{x}}{d}\)
所以原式 =
预处理一下\(f\) 即可。
分别跑一个整除分块即可。
P3911 最小公倍数之和
对于\(A_1,A_2,\cdots,A_N\),求
的值。
\(\mathrm{lcm}(a,b)\) 表示 \(a\) 和 \(b\) 的最小公倍数。
改写一下,记 \(n\) 表示 \(A_i\) 中的最大值,\(cnt_i\) 表示 \(i\) 出现过的次数。
为了方便描述,记 \([i \div j]\) 表示 \(i \div j\) 向下取整。
那么可以改写式子为:
两部分分开搞。对于 \(\mu\) 的前缀和求解,具体方法在上文说过,这里不过多赘述。后面的东西暴力算即可。

浙公网安备 33010602011771号