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\),减一是因为要剪掉根节点。

那么可以得到转移如下:

\[f_{i, j} = \sum_{k = 0}^{k < i} f_{k, j - 1} \times f_{n - k - 1, j - 1} \]

时间复杂度 \(O(n^3)\),可以通过本题。

CF10D LCIS

题意:求两个串的最长公共上升子序列。(太精简了捏。)

首先,在求最长上升子序列时,是记录了一个末尾 \(b_i\) 的最长上升子序列的数量。

然后,在求最长公共子序列时,是记录了一个 \(f_{i, j}\) 表示从 \(a\) 的前 \(i\) 个与 \(b\) 的前 \(j\) 个选出的最长公共子序列。

整合一下可以及 \(f_{i, j}\) 表示在 \(a\) 的前 \(i\) 个数中,结尾为 \(b_j\) 的最长公共上升子序列的长度。

枚举 \(i, j\) 后进行分类讨论:

  1. \(a_i \not= b_j\) ,直接转移 \(f_{i, j} = f_{i - 1, j}\) 因为 \(j\) 是必选的,所以 \(j\) 不能改变。
  2. \(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\) 步走向右的操作。

所以转移为:

\[f_i = C_{x_i + y_i - 2} ^ {x_i - 1} - \sum_{j = 1} ^ {i - 1} C_{x_i + y_i - x_j - y_j} ^ {x _ i - x_j} \times f_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\) 儿子节点集合。

则有如下转移:

\[f_{i, 0} = \sum_{j \in son_i} \max(f_{j, 0}, f_{j, 1})\\ f_{i, 1} = \sum_{j \in son_i} f_{j, 0} + a_i \]

然后只需要找一下根节点即可。由于是有向边,入度为 \(0\) 的就是根节点。

2023-10-31

P1390 公约数的和

给定 \(n\), 求

\[\sum_{i = 1} ^ {n} \sum_{j = i + 1} ^ {n} \gcd(i, j) \]

先让 \(j\)\(1\) 开始,最后剪掉重复计算部分即可。

那么,式子,启动 。

\[\sum_{i = 1} ^ {n} \sum_{j = 1} ^ {n} d \times [gcd(i, j) == d]\\ \sum_{d = 1} ^ {n} d \times \sum_{i = 1} ^ {n \div d} \sum_{j = 1} ^ {n \div d} [\gcd(i, j) == 1]\\ \sum_{d = 1} ^ {n} d \times \sum_{i = 1} ^ {n \div d} \sum_{j = 1} ^ {n \div d} \sum_{e | \gcd(i, j)} \mu(e)\\ \sum_{d = 1} ^ {n} d \times \sum_{e = 1} ^ {n} \mu(e) \times \sum_{i = 1} ^ {n \div d \div e} \sum_{j = 1} ^ {n \div d \div e}\\ \sum_{d = 1} ^ {n} d \times \sum_{e = 1} ^ {n} \mu(e) \times \left \lfloor \frac{n}{de} \right \rfloor\left \lfloor \frac{n}{de} \right \rfloor \\ \]

\(D = de\)

\[\sum_{D = 1} ^ {n}\sum_{d | D} d \times \mu(e) \times \left \lfloor \frac{n}{D} \right \rfloor\left \lfloor \frac{n}{D} \right \rfloor \\ \because id * \mu = \phi\\ \therefore 原式 = \sum_{D = 1} ^ {n} \phi(D) \times \left \lfloor \frac{n}{D} \right \rfloor\left \lfloor \frac{n}{D} \right \rfloor \\ \]

预处理一下 \(\phi\) 的前缀和,套个整除分块即可。

P2257 YY的GCD

题意:

\[\sum_{x = 1} ^ n \sum_{y = 1} ^ m [\gcd(x, y) \in prime]\\ \sum_{k = 1} ^ n \sum_{x = 1} ^ n \sum_{y = 1} ^ m [\gcd(x, y) == k] (k \in prime)\\ \sum_{k = 1} ^ n \sum_{x = 1} ^ {n \div k} \sum_{y = 1} ^ {m \div k}[\gcd(x, y) == 1] (k \in prime)\\ \sum_{k = 1} ^ n \sum_{x = 1} ^ {n \div k} \sum_{y = 1} ^ {m \div k} \sum_{d | \gcd(x, k)} \mu(d) (k \in prime) \\ \sum_{k = 1} ^ n \sum_{d = 1} ^ {n \div k} \mu(d) \sum_{x = 1} ^ {n \div k \div d} \sum_{y = 1} ^ {m \div k \div d} (k \in prime)\\ \sum_{k = 1} ^ n \sum_{d = 1} ^ {n \div k} \mu(d) \times \left \lfloor \frac{n}{dk} \right \rfloor\left \lfloor \frac{m}{dk} \right \rfloor (k \in prime)\\ 记 D = dk\\ 原式 = \sum_{D = 1} ^ {n} \sum_{k | D (k \in prime)} \mu(\frac{D}{k}) \times \left \lfloor \frac{n}{D} \right \rfloor\left \lfloor \frac{m}{D} \right \rfloor\\ \sum_{D = 1} ^ {n}\left \lfloor \frac{n}{D} \right \rfloor \left \lfloor \frac{m}{D} \right \rfloor \sum_{k | D (k \in prime)} \mu(\frac{D}{k}) \]

可以枚举 \(D\),预处理后面的东西。具体来说就是用欧拉筛筛完质数和 \(\mu\) 过后枚举每个质数的 \(x\) 倍,倍数的答案加上 \(\mu(x)\) 即可。

在求个前缀和,整除分块搞一下即可。

P3810 【模板】三维偏序(陌上花开)

等后面的 \(CDQ\) 学习笔记吧。

P3195 [HNOI2008] 玩具装箱

首先写出一个 \(O(n ^ 2)\) 的简单 \(dp\)

\(dp_i\) 表示收纳前 \(i\) 个玩具需要的最小花费,\(sum_i\) 表示 \(C_i\) 的前缀和,那就可以得到如下转移:

\[dp_i = \min(dp_j + (j - i - 1 + sum_i - sum_j - L) ^ 2)(j < i) \]

由于我不想证明决策单调性,所以这里就不写了,写一下推式子的过程吧。

这里记 \(f_i = sum_i + 1, L = L + 1\)。(主要方便后面化简)

假设有 \(k > j\) 且决策点 \(k\) 比决策点 \(j\)

\[dp_j + (f_i - f_j - L) ^ 2 > dp_k + (f_i - f_k - L) ^ 2\\ dp_j + (f_i - (f_j + L)) ^ 2 > dp_k + (f_i - (f_k + L)) ^ 2\\ dp_j + f_i ^ 2 - 2f_i(f_j + L) + (f_j + L) ^ 2 > dp_k + f_i ^ 2 - 2f_i(f_k + L) + (f_k + L) ^ 2\\ 化简得到:\\ 2f_i(f_k - f_j) > dp_k - dp_j + (f_k + L) ^ 2 - (f_j + L) ^ 2\\ f_i > \frac{dp_k - dp_j + (f_k + L) ^ 2 - (f_j + L) ^ 2}{f_k - f_j} \]

也就是说只要满足 \(k > j\) 且满足上述条件,那么用更新 \(k\) 一定比 \(j\) 优,拿个单调队列维护即可。

P3628 [APIO2010] 特别行动队

先写出一个 \(O(n ^ 2)\) 的简单 \(dp\)

这里记 \(dp_i\) 表示选前 \(i\) 个人,战力最大是多少,\(sum_i\)\(x_i\) 的前缀和,得到如下转移:

\[dp_i = \max(dp_j + a(sum_i - sum_j) ^ 2 + b(sum_i - sum_j) + c) \]

假设有 \(k > j\) 且决策点 \(k\) 比决策点 \(j\) 优:

\[dp_j + a(sum_i - sum_j) ^ 2 + b(sum_i - sum_j) + c < dp_k + a(sum_i - sum_k) ^ 2 + b(sum_i - sum_k) + c\\ dp_j + a(sum_i ^ 2 - 2 sum_i sum_j + sum_j ^ 2) + b sum_i - b sum_j < dp_k + a(sum_i ^ 2 - 2 sum_i sum_k + sum_k ^ 2) + b sum_i - b sum_k\\ dp_j + a sum_i ^ 2 - 2a sum_isum_j + asum_j ^ 2 + b sum_i - b sum_j < dp_k + a sum_i ^ 2 - 2a sum_isum_k + asum_k ^ 2 + b sum_i - b sum_k\\ 化简得:\\ dp_j - 2a sum_isum_j + asum_j ^ 2 - b sum_j < dp_k - 2a sum_isum_k + asum_k ^ 2 - b sum_k \\ 移项得:\\ 2asum_i(sum_k - sum_j) < dp_k - dp_j + ausm_k ^ 2 - asum_j ^ 2 - b sum_k + b sum_j\\ sum_i < \frac{p_k - dp_j + ausm_k ^ 2 - asum_j ^ 2 - b sum_k + b sum_j}{2a(sum_k - sum_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\) 块土地的最小代价,得到转移:

\[dp_i = min(dp_j + w_j \times l_i) \]

假设有 \(k > j\) 且决策点 \(k\) 比决策点 \(j\) 优:

\[dp_j + w_j \times l_i > dp_k + w_k \times l_i\\ l_i(w_j - w_k) > dp_k - dp_j\\ \because j < k \therefore w_j > w_k\\ l_i > \frac{dp_k - dp_j}{w_j - w_k} \]

也就是说只要满足 \(k > j\) 且满足上述条件,那么用更新 \(k\) 一定比 \(j\) 优,拿个单调队列维护即可。

P2522 [HAOI2011] Problem b

给定 \(a, b, c, d, k\),求:

\[\sum_{x = a} ^ {x \le b} \sum_{y = c} ^ {y \le d} [\gcd(x, y) == k] \]

先不管是从 \(a, b\) 开始枚举的,这个后面容斥掉即可,那么式子就成了:

\[\sum_{x = 1} ^ n \sum_{y = 1} ^ m[\gcd(x, y) == k]\\ \sum_{x = 1} ^ {n \div k} \sum_{y = 1} ^ {m \div k} [\gcd(x, y) == 1]\\ \sum_{x = 1} ^ {n \div k} \sum_{y = 1} ^ {m \div k} \sum_{d | gcd(x, y)} \mu(d)\\ \sum_{d = 1} ^ {n} \mu(d) \left \lfloor \frac{n}{dk} \right \rfloor \left \lfloor \frac{m}{dk} \right \rfloor \]

前缀和预处理 \(\mu\),跑整除分块即可算出答案。

最后容斥一下,记算上面那个式子为 \(f_{i, j}\)

\[ans = f_{b, d} - f_{b, c - 1} - f_{a - 1, d} + f_{a - 1, c - 1} \]

这样就做完了。

P2158 [SDOI2008] 仪仗队

由于能被看到一定是在中间没有经过任何的其他点,所以能被看到的点的 \(x, y\) 互质。

又因为给定的 \(n\) 是点的个数,需要求的互质是以边来看的,所以应该是 \(n - 1\) 范围以内的。

所以的答案为:

\[\sum_{i = 1} ^ {n - 1} \sum_{j = 1} ^ {n - 1} [\gcd(i, j) == 1] \]

现在就有了两种做法,一种拿莫反跑,一种拿欧拉函数跑。由于我第一次推的式子是莫反的,所以这里说莫反吧。

开始推式子:

\[\sum_{i = 1} ^ {n - 1} \sum_{j = 1} ^ {n - 1} [\gcd(i, j) == 1]\\ \sum_{i = 1} ^ {n - 1} \sum_{j = 1} ^ {n - 1} \sum_{d | gcd(i, j)} \mu(d)\\ \sum_{d} ^ {n - 1} \mu(d) (\frac{n - 1}{d}) ^ 2 \]

虽然 \(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\) 的前缀和。

可以得到如下转移:

\[dp_i = min(dp_j + sumt_i \times (sumc_i - sumc_j) + s \times (sumc_n - sumc_j)) \]

这样就可以过掉 \(P2356\)

考虑优化。

假设有 \(k > j\) 且决策点 \(k\) 比决策点 \(j\) 优:

\[dp_j + sumt_i \times (sumc_i - sumc_j) + s \times (sumc_n - sumc_j) > dp_k + sumt_i \times (sumc_i - sumc_k) + s \times (sumc_n - sumc_k)\\ dp_j - sumt_i \cdot sumc_j - s \cdot sumc_j > dp_k - sumt_i \cdot sumc_k - s \cdot sumc_k\\ sumt_i(sumc_k - sumc_j) > dp_k - dp_j + s \cdot sumc_j - s \cdot sumc_k\\ \because k > j \therefore sumc_k > sumc_j\\ sumt_i > \frac{dp_k - dp_j + s \cdot sumc_j - s \cdot sumc_k}{sumc_k - sumc_j}\\ \]

你认为这样再上个优先队列就完了?

\(no,no,no\) 再仔细地读一下题你会发现 \(t_i\) 有可能会小于 \(0\)。这就意味着 \(sumt\) 不在是一个单调的序列了。

那这该怎么办呢?

由于 \(sumt\) 并不单调,所以这就意味着不能通过判断相邻两点的关系来弹出队头了。

但队尾的比较并不影响,所以就变成了一个单调栈。

至于查找最优决策点,二分一下即可。时间复杂度 \(O(n ^ 2)\)

P3327 [SDOI2015] 约数个数和

给定 \(n, m\),求:

首先需要知道 (我也不知道怎么证的,背就完了)

\[d(i, j) = \sum_{x | i} \sum_{y | j} [\gcd(x, y) == 1]\\ 所以原式 = \sum_{i = 1} ^ n \sum_{j = 1} ^ m \sum_{x | i} \sum_{y | j} [\gcd(x, y) == 1]\\ 改为枚举x, y\\ \sum_{x = 1} ^ n \sum_{y = 1} ^ m \left \lfloor \frac{n}{x} \right \rfloor \left \lfloor \frac{m}{y} \right \rfloor [\gcd(x, y) == 1]\\ \sum_{x = 1} ^ n \sum_{y = 1} ^ m \sum_{d | \gcd(x, y)} \mu(d) \left \lfloor \frac{n}{x} \right \rfloor \left \lfloor \frac{m}{y} \right \rfloor\\ \sum_{d = 1} ^ n \mu(d) \sum_{x = 1} ^ {n \div d} \sum_{y = 1} ^ {m \div d} \left \lfloor \frac{n}{xd} \right \rfloor \left \lfloor \frac{m}{yd} \right \rfloor\\ 根据乘法分配律可得:\\ \sum_{d = 1} ^ n \mu(d) \sum_{x = 1} ^ {n \div d} \left \lfloor \frac{n}{xd} \right \rfloor \sum_{y = 1} ^ {m \div d} \left \lfloor \frac{m}{yd} \right \rfloor\\ \]

\(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}\)

所以原式 =

\[\sum_{d = 1} ^ n \mu(d) f_{\left \lfloor \frac{n}{d} \right \rfloor} f_{\left \lfloor \frac{m}{d} \right \rfloor} \]

预处理一下\(f\) 即可。

分别跑一个整除分块即可。

P3911 最小公倍数之和

对于\(A_1,A_2,\cdots,A_N\),求

\[\sum_{i=1}^N\sum_{j=1}^N \mathrm{lcm}(A_i,A_j) \]

的值。

\(\mathrm{lcm}(a,b)\) 表示 \(a\)\(b\) 的最小公倍数。

改写一下,记 \(n\) 表示 \(A_i\) 中的最大值,\(cnt_i\) 表示 \(i\) 出现过的次数。

为了方便描述,记 \([i \div j]\) 表示 \(i \div j\) 向下取整。

那么可以改写式子为:

\[\sum_{i = 1} ^ n \sum_{j = 1} ^ n lcm(i, j) \times cnt_i \times cnt_j\\ \sum_{i = 1} ^ n \sum_{j = 1} ^ n i \times j \div \gcd(i, j) \times cnt_i \times cnt_j\\ \sum_{i = 1} ^ n \sum_{j = 1} ^ n \sum_{k = 1} ^ n [\gcd(i, j) == k] \frac{i \times j}{k} \times cnt_i \times cnt_j\\ \sum_{k = 1} ^ n \sum_{i = 1} ^ {[n \div k]} \sum_{j = 1} ^ {[m \div k]} [\gcd(i, j) == 1] i \times j \times k \times cnt_{ik} \times cnt_{jk}\\ \sum_{k = 1} ^ n \sum_{i = 1} ^ {[n \div k]} \sum_{j = 1} ^ {[m \div k]} \sum_{d | gcd(i, j)} \mu(d) i \times j \times k \times cnt_{ik} \times cnt_{jk}\\ \sum_{k = 1} ^ n \sum_{d = 1} ^ {[n \div k]} \mu(d) d ^ 2 \sum_{i = 1} ^ {[n \div k \div d]} \sum_{j = 1} ^ {[m \div k \div d]} i \times j \times k \times cnt_{ikd} \times cnt_{ikd}\\ 记 T = kd\\ \sum_{T = 1} ^ n T\sum_{d | T} \mu(d) d \sum_{i = 1} ^ {[n \div T]} \sum_{j = 1} ^ {[m \div T]} i \times j \times k \times cnt_{iT} \times cnt_{iT}\\ \sum_{T = 1} ^ n T\sum_{d | T} \mu(d) d (\sum_{i = 1} ^ {[n \div T]} i \times cnt_{iT}) ^ 2 \]

两部分分开搞。对于 \(\mu\) 的前缀和求解,具体方法在上文说过,这里不过多赘述。后面的东西暴力算即可。

posted @ 2023-11-24 17:27  Populus_euphratica  阅读(27)  评论(0)    收藏  举报