Tricks & 注意事项

  • 求答案第 \(k\) 大/前 \(k\) 大问题

  • 指数乘积拆解:\(\displaystyle ij=\binom{i+j}{2}-\binom{i}{2}-\binom{j}{2}\)

    \[a^{ij}=\frac{a^{\large\binom{i+j}{2}}}{a^{\large\binom{i}{2}}a^{\large\binom{j}{2}}} \]

    应用:P6295

  • 若干个集合,每个集合有若干个数,每次删去两个不同集合中的一个数,求最后最少剩下几个数。

    \(k\) 为集合大小最大的一个集合,\(siz(x)\) 表示 \(x\) 集合的大小,\(sum\) 表示所有集合的大小的和:

    • \(siz(k) \le sum - siz(k)\),那么每次删除最大值与次小值,最后只剩下 \(0/1\) 个数。
    • \(siz(k) > sum - siz(k)\),那么每次用 \(k\) 集合里的一个数与其它集合里的一个数删除,最后只剩下 \(siz(k) - (sum - siz(k)) = 2siz(k) - sum\) 个数

    应用:AGC034E

  • 没有负环 → 差分约束有合法解

    应用:AGC036D

  • 《b i t s e t 字 符 串 匹 配》

    应用:CF914F

  • 对于期望方程组类型的题目,且矩阵相对稀疏,可以考虑递推系数的方法消除大部分未知数。

  • 无穷级数求和:可以先推导出生成函数的封闭形式(尤其是涉及到组合数一类的无穷级数求和),然后将 \(x=1\) 带入。如果有指数形式的可以直接带 \(x=a\) 实现系数乘 \(a^n\)

  • 贝尔级数 可以比较轻松解决一些杜教筛/狄利克雷卷积的问题?

    有生之年也不知道能不能碰上的)

    eg. \(f(1)=1,f(p^c)=p^c+(-1)^c \Rightarrow f_p(x)=ID_p(x)+\lambda_p(x)-e_p(x) \Rightarrow \frac{1-px^2}{(1-px)(1+x)}\)

    这有啥用啊,卷完也不会做)

  • \(\sum_{i=1}^n \mu^2(i)=\sum_{i\leq\sqrt n} \lfloor\frac{n}{i^2}\rfloor\mu(i)\)

  • 我发现不知道为啥,我永远见题想不到倍增。

  • 字符串出现次数:

    • 在线:建 SAM
    • 离线:建 AC 自动机
    • 如果模式串极长(由规律给出)考虑 AC 自动机 GYM103409H
    • bitset 匹配 CF914F
  • 给定字符串 \(s,t\)\(q\) 次询问,每次找 \(s\) 的一个子串在 \(t\) 的 SAM 上的对应节点:

    首先将 \(s\)\(t\) 上跑一遍,记录下每一个前缀在 \(t\) 上能匹配的最大后缀所代表的节点。

    查询时直接在最长的节点倍增跳 \(fail\) 即可 \(O(\log n)\) 查找单个节点。

    注意当最长节点的长度小于询问串的情况。

    int get(int p, int l) {
        for (int i = 19; i >= 0; i--) {
            int q = fa[p][i];
            if (len[q] >= l) p = q;
        }
        return p;
    }
    

    应用:CF666E 【ULR #1】打击复读

  • 对于一个字符串的正反 SAM,可 \(O(n)\) 找到正串某个节点代表的最长字符串对应的反串节点与正串某个节点代表的所有字符串对应的反串节点的权值和。

    大体做法是压缩后缀自动机中出度为 \(1\) 的节点,具体看 题解

  • 树形 DP 中如果需要记录顶点所在连通块的大小,可以转化成从顶点所在连通块中选出一个关键点来将 \(0\sim siz_u\) 的状态压缩到 \(0 \sim 1\)(仅记录是否已经选取关键点)

  • 树上 \(dep_{lca(u,v)}\)

    • \(dep_{lca(u,v)}=\frac{dep_u+dep_v-dis_{u,v}}{2}\)

    • \(dep_{lca(u,v)} = \sum_{i\in T} [u\in T(i)][v \in T(i)]\)

  • 求最大值最小:二分答案。
    感觉总是想不起来二分答案,大概需要恶补一下二分答案(

  • \(\min_{i\in S} a_i\),可以拆成 \(\sum_{T\subseteq S} f(T)\),其中 \(f(\{a_{p_1},a_{p_2},\cdots,a_{p_{j-1}}\})=a_{p_j} - a_{p_{j-1}}\)\(a_{p_1}<a_{p_2}<\cdots<a_{p_n}\)),于是可以快速计算 \(\sum \min\) 的和。

  • 按照奇偶性对题目进行转换能得出一些东西。
    比如一个 01 串,每次可以对两个相邻的相等的数翻转,如果对奇数位异或 \(1\) 之后就变成了每次可以交换相邻的 0 和 1。
    或者字符串问题,按照奇偶性重新构造一个字符串可能会有更好的性质。

  • 覆盖连续值域:扫描线,然后可以转换成维护 \((\max - \min) - (r - l)\) 的最小值数量。
    如果有重复元素,那么对于每一个右端点来说,其不含重复元素的左端点一定是在某一个区间,且这个分界点随着右端点的移动而向右移,所以可以直接维护一些这个端点,然后只查询这个区间内的 \((\max - \min) - (r - l)\) 的最小值数量即可。

  • 主席树带修:树状数组套主席树

  • 选中概率为 \(p\),那么选中的期望次数为 \(\frac{1}{p}\)

  • 赠券收集问题:有 \(n\) 个物品,每次随机选择到一个,选择到所有的物品的期望次数为 \(\sum_{i=1}^n \frac{n}{i}\)

  • 异或和最大/最小问题:扔 Trie 树上,在 Trie 树上统计答案。
    异或和不等于 \(0\):线性基,每个数线性无关。

  • 树上启发式合并可以应用到区间分裂、笛卡尔树上。link

  • 将字符串子串分割成特定的形式的方案数(\(AA\) 等):可以通过枚举长度,然后设置关键点计算。link

  • 区间加等差数列区间求最小/最大值:分块维护凸包 link

  • 分治优化 DP:

    • 决策单调性优化
    • 如果转移系数有很多相同,可以考虑能否使转移与 \(i\) 无关,这样就可以批量转移。
      比如 \(next(f_i, x) = next(f_{mid}, x)\)
    • \(f_i\) 具有单调性,那么可以仅考虑对它有贡献的 \(f_j\)
  • 区间 \(\max\) 满足四边形不等式。

  • \[\binom{-n}{m} = (-1)^m\binom{n + m - 1}{m} \]

    脑子能不能记点东西啊你,每次碰到这个都要现推(

  • \(\binom{n}{m}\)\(n\) 很大的时候可以使用 \(\frac{n^{\underline{m}}}{m!}\) 计算。
    可以使用 \(\binom{n+1}{m}=\binom{n}{m}\times \frac{n+1}{n-m+1}\) 快速计算。
    避免被卡模数:可以每次判断如果当前值为 0 但组合数不应该等于 0 时暴力重算,暴力重算只会重算一次,所以没啥事。

    if (comb == 0 && (n - m) % P <= n % P) comb = C(n, m);
    
  • \(f_{i,j}\) 且第二维具有凸性 / 同剩余系具有凸性的 DP 可能可以使用分治 + 闵可夫斯基和解决。link

  • 代表元思想:树上连通块用深度最小的点代表,树上分割连通块可以用每个联通块深度最小的点到父亲的边权和表示

  • 求所有方案的权值和,且权值为加的形式:对每种贡献求包含这种贡献的方案数然后加和。
    比如 DP 求所有方案的逆序对数和、DP 求所有方案的环数和 etc.

  • 非严格偏序 \(\pm 1\) 变成严格偏序会有更优秀的性质

  • 求经过某种操作序列能够得到的不同的状态数的题:

    • 探究一下什么状态能够被得到,由此而不是由操作序列的角度设计 DP 状态。
    • 硬是从操作序列的角度入手,不过给操作序列定个顺序(比方说,字典序最小的操作序列),以保证任意一个合法的状态只会被算一次。
  • \[\int_0^1 x^a(1-x)^b {\rm d} x = \frac{a!b!}{(a+b+1)!} \]

  • 求随机过程的结束期望时间:

    • 状态有单调性:可以将期望时间拆分成在每个状态上浪费的时间,那么答案就是每种不合法状态乘离开这个状态的期望时间的和。\(\sum_S \frac{1}{P(S)}\) ABC242H
    • 状态无单调性:可以拆成三个值:从初始状态第一次到终止状态(所求答案),从终止状态到终止状态,从起始状态到终止状态,把三者写成生成函数,关系为 \(F(x)G(x)=H(x)\),这样就去除掉了第一次的限制,所求的答案为 \(F'(1)=\frac{H'(1)G(1)-H(1)G'(1)}{G(1)^2}\)ARC136F
    • 状态无单调性,局面较为复杂:构造局面的势能函数使得 \(E(\Phi(A_{n+1})-\Phi(A_n)) = -1\),这样结束期望时间为 \(\Phi(A_0) - \Phi(A_T)\)。(鞅的停时定理)
  • 求形如 \(\sum (x+a)^i(x+b)^{n-i}\) 一类的多项式时,先换元 \(y=x+a\) 消掉一个多项式幂,再转回去。

  • 归约矩乘,碰到直接想根号做法。

  • 博弈论中的“决策包容性”:如果当前状态可以到达某个后继状态的所有后继状态,那么这个状态一定是必胜态。
    因为如果这个后继状态为必胜态,那它的后继状态一定都是必败态,所以当前状态一定是必胜态。 ARC137C

  • 带有 \(\max / \min\) 等类型的函数的求和可以拆分成多项式分段函数,分别插值计算。
    P8290 去年考场上我好像还想到了可以写成分段函数的形式,但是当时想的是维护这个函数,然后我不会维护,没想到可以插值。

  • 限制最大值减最小值小于等于 \(k\):先求出每个值域长度为 \(k\) 的答案,减去每个值域长度为 \(k-1\) 的答案。(考虑枚举最大值 \(r\),那么钦定最大值选的答案就是 \([r - k + 1, r]\) 的答案减去 \([r - k + 1, r - 1]\) 的答案,对所有的 \(r\) 求和即为 \(k\) 减去 \(k-1\)

  • DP 中如果最终答案统计与某一维有关,可以尝试用另一个 DP 数组来同时转移答案来消除记录这一维的必要性,从而降低状态数。

  • 环染色方案数:\(f_n = (m-1)^n + (-1)^n (m-1)\) \((m \ge 2)\)
    证明:不考虑 \(1\)\(n\) 的颜色不同的染色方案数为 \(m (m-1)^{n - 1}\),然后容斥一下,就是 \(f_n = m (m-1)^{n - 1} - f_{n - 1}\),解得上式。

  • 见生成函数递推式想倍增。

  • 区间覆盖可以用并查集方便的做,用并查集维护每个点的下一个未被覆盖过的点的位置,区间覆盖时从左端点开始跳然后将当前点合并到下一个点上。

    for (int j = find(l); j <= r; j = find(j)) {
    	val[j] = i, fa[j] = j + 1;
    }
    
  • \(n\times m\) 行满秩矩阵数为 \(\displaystyle \prod_{i=0}^{m-1}(p^n-p^i)\)。特别的,可逆矩阵数为 \(\displaystyle \prod_{i=0}^{n-1}(p^n-p^i)\)

  • \(n\) 个点的堆的方案数为 \(\frac{n!}{\prod siz_i}\)
    考虑朴素做法 \(f_u = \binom{siz_u - 1}{siz_{lc}} f_{lc} f_{rc}\),然后暴力拆开组合数可以消掉一堆阶乘,剩下上式。

  • \(O(V \log V)\)\(n\) 个数的 \({\rm lcm} \bmod P\)\(V\) 为值域):

    for (int i = 1; i <= n; i++) {
    	vis[a[i]] = 1;
    }
    for (int i = 2; i <= V; i++) {
    	pri[i] = 1;
    }
    for (int i = 2; i <= V; i++) {
    	for (int j = i * 2; j <= V; j += i) {
    		vis[i] |= vis[j], pri[j] = 0;
    	}
    }
    int lcm = 1;
    for (int i = 2; i <= V; i++) if (pri[i]) {
    	for (long long j = i; j <= V && vis[j]; j *= i) {
    		lcm = lcm * i % P;
    	}
    }
    
  • 中位数相关问题:设大于等于 \(k\) 的数为 \(1\),小于 \(k\) 的数为 \(0\),那么中位数大于等于 \(k\) 当且仅当新序列中位数为 \(1\)

  • \(c \ge x, c \gets c - x\) 有关的问题考虑 值域倍增分块

  • 多元限制转一元限制:减半警报器

  • 对于求区间内点对贡献最小值/最大值 or 区间内 \(\mathrm{lca}\) 相关问题:支配对

  • 最大团 = 补图的最大独立集

  • \(\mathrm{det}(A) \ne 0 \Leftrightarrow A\) 满秩;
    \(A\) 的秩相当于删去最少的行列,使得行列式不等于 \(0\)

  • 树上 \(u - [l, r]\)\(\mathrm{lca}\) 最浅:\([l, r]\)\(\mathrm{dfn}\) 序最大 / 最小;
    树上 \(u - [l, r]\)\(\mathrm{lca}\) 最深:\([l, r]\)\(\mathrm{dfn}\) 序的前驱 / 后继。

  • \(k\) 次方的期望:设 \(P(x)\) 为概率生成函数,那么

    • \([x^k]P(e^x)\)(复合求法:\(e^{ix}\) 转成 \(\frac{1}{1-ix}\),分治乘法后再乘上 \(\frac{1}{i!}\));
    • \(\sum_{i=0}^k {n \brace k} P^{(i)}(1)\)
  • \(\max\) 卷积:

    \[h_k = \sum_{\max(i, j) = k} f_i g_j \]

    \[\sum_{k=0}^x h_k = \left(\sum_{i=0}^x f_i\right)\left(\sum_{j=0}^x g_j\right) \]

    前缀和,点乘,再差分即可。

  • 树上黑白连通块:
    白连通块数量 = 黑白边数 = 白点数 - 白白边数

  • 树上距离 \(\le d\) 的信息维护:点分树,每次找距离分支中心小于等于 \(d - dep_u\) 的点的信息。

  • 一个随机排列的最长上升子序列的长度期望是 \(O(\sqrt{n})\) 的。

    • 根据 Dilworth 定理,可得出一个随机排列划分成最少个下降子序列的数量的期望是 \(O(\sqrt{n})\) 的。
      具体构造可以考虑跑 LIS 的过程中,当一个数在二分过程后被替换掉时,将新的数挂到替换掉的数下,这样就能划分出 LIS 条下降子序列。
      根据这一性质,任意一道回滚莫队可以做的题在随机数据下都可以做,复杂度相同且不需要支持撤销。具体做法就是按照询问左端点排序,然后将右端点划分成根号个下降序列,这样每个操作序列的区间只会往外拓展。
  • 一类单次 check 为 \(O(a_i)\)\(\sum a_i = O(n)\) 的二分问题可以先倍增后二分。(比如将序列划分成 \(k\) 段,每次找分割点需要二分的问题)
    倍增可以以 \(O(a_i \log a_i)\) 的复杂度将答案确定至 \(\lbrack a_i, 2a_i)\),然后再以 \(O(a_i \log a_i)\) 的复杂度在这个区间内二分,这样单次复杂度由 \(O(n \log n)\) 降低至 \(O(a_i \log a_i)\),总复杂度从 \(O(nk \log n)\) 降低至 \(\sum O(a_i \log a_i) = O(n \log n)\)

  • 树上构造考虑剥叶子。树上构造考虑剥叶子。树上构造考虑剥叶子。

  • 带限制的不相交路径计数:LGV 引理中的权值可以为多项式,尝试把限制转化为多项式提取系数,然后插值得出答案。

  • 期望题中一类形如从当前局面中选取一个数并删除的题目,由于概率 \(\frac{a}{b}\) 中的 \(b\) 与当前局面有关,每种选择的概率不固定,并不好直接拆开贡献。考虑类似于拒绝采样的方法,将从当前局面中选择转化为在全局中选择,如果选择的数不在当前局面中就重新选择,这样概率不变且使得每次选择的概率固定。

  • LCT access 均摊:每次修改根到某个点的树链,每次经过的连续颜色端数是均摊 \(O(\log n)\) 的,所以可以在 access 的同时维护连续段的信息。

  • 树形背包可以用过 DFS 序上 DP 优化复杂度。与连通性相关的可通过树剖 / 点分治降低状态数。

  • SAM 中每个节点之间的 \(endpos\) 集合相邻对数是 \(O(n \log n)\) 的,可以通过启发式合并的方式维护。

  • 字符串问题中,跨过某位置的子串可以看做是一个后缀与一个前缀拼接成的。

  • 对于任意满足四边形不等式的最短路问题(\(f_{i,j} = \min_{1\le k<j} f_{i-1,k} + w_{k, j}\)),\(f_{k,n}\) 关于 \(k\) 是凸函数,即可以通过 wqs 二分去掉第二维。P9338

  • 线性规划对偶:

    对于系数矩阵:

    \[\begin{matrix} & x_1 & x_2 &\cdots & x_n & \\ y_1 &A_{1,1}&A_{1,2}&\cdots &A_{1,n}& a_1 \\ y_2 &A_{2,1}&A_{2,2}&\cdots &A_{2,n}& a_2 \\ \vdots &\vdots &\vdots &\ddots &\vdots &\vdots \\ y_m &A_{m,1}&A_{m,2}&\cdots &A_{m,n}& a_m \\ & b_1 & b_2 &\cdots & b_n & \\ \end{matrix} \]

    线性规划问题:

    \[\begin{array}{ccc} \text{minimize } & \sum_{i=1}^n b_i x_i\\ \text{s.t. } & \forall j \in [1, m], \sum_{i=1}^n A_{j, i} x_i \ge a_j \end{array} \]

    与:

    \[\begin{array}{ccc} \text{maximize } & \sum_{i=1}^m a_i y_i\\ \text{s.t. } & \forall j \in [1, n], \sum_{i=1}^m A_{i, j} y_i \le b_j \end{array} \]

    对偶。

  • bitset 可以 \(O\left(\frac{n}{w}\right)\) 进行区间查询,但是空间是无法接受的,可以按照 \(O\left(\frac{n}{w}\right)\) 进行分块,这样空间复杂度 \(O(nw)\),时间复杂度仍然是 \(O\left(\frac{n}{w}\right)\)。对于可差分的信息(异或),直接维护前缀和即可,对于可重复覆盖的信息(与,或),可以对块建 ST 表,空间复杂度 \(O(nw \log w)\)

  • 可以离线扫描线的问题,如果可以改为根号重构且空间允许,则可以按照根号重构的方法在线做。

  • 区间并查集合并:对于区间 \([l, r], [l', r']\),让 \(l - l', l + 1 - l' + 1, \cdots, r - r'\) 合并。可以考虑倍增处理,对于每一个长度为 \(2^k\) 的区间建并查集,合并时将 \(\log n\) 个区间进行合并,然后从上到下 pushDown 一遍即可。

posted @ 2022-10-09 11:36  APJifengc  阅读(453)  评论(1编辑  收藏  举报