W
H
X

Before NOIP2021

10月末开始会记的少一些。

9.25

P7110 晚秋绝诗

有雾有旗的山可以起到传递作用,把它们删掉之后,如果有两个相邻的无雾的山,那么它们中间的这些都可以确定。对于一个询问,分类讨论,是直接确定,通过左边/右边确定还是两边一起确定。用若干set来维护信息即可。

P4800 [CEOI2015 Day2]核能国度

二维差分,二次差分(在对角线上搞)

P4654 [CEOI2017]Mousetrap

贪心dp一下就行了?写了三种代码,其中一种是线性的。得分72——92。不知道哪里错了,最后只能“特判”。反正思路应该没啥问题

9.26

CF603E Pastoral Oddities

满足条件当且仅当所有连通块大小为偶数。必要性:选出的子图一定是若干偶数连通块,那么原图中的连通块也只能是偶数。充分性:每个偶数连通块选出一个生成树,然后一定可以在树上构造出来(dfs一遍,度数为偶就断开和父节点的边)。
如果暴力算一次答案,只需把所有边排序,依次加入,直到符合要求。因为多加边不会更劣。
对于原问题,根据答案单调性,使用带答案上下界的CDQ分治。给答案一个上下界是为了在递归每一层计算的时候每条边只被修改 \(O(1)\) 次。

P3352 [ZJOI2016]线段树

先考虑容斥转化成01序列处理:枚举 \(p\),计算最后 \(a_x \leq p\) 的概率,只需要知道 \(a_i\)\(p\) 的大小关系,设 \(b_i=[a_i>p]\)
在操作中,\(1\) 会向外拓张,\(0\) 只能被覆盖。设 \(f_{i,l,r}\) 表示 \(i\) 轮后 \([l,r]\) 全是 \(0\) 的概率,分类转移。用前后缀和优化可以做到 \(O(n^3q)\)
然后发现其实对于不同的 \(p\) 转移的过程相同,而且最终的答案和赋的初值是线性关系。那么直接把每一种答案的贡献弄到 \(f\) 的初值里,递推一遍即可得到所有答案。
因为数列随机,似乎不用优化也是 \(O(n^2q)\)?
question:"序列随机"意味着对于位置 \(x\)\(a_x\) 最后可能得到的值只有 \(\log n\) 种,能否根据这个条件得到新的做法?

P5466 [PKUSC2018]神仙的游戏

若前缀 \(i\) 为 border,则 \(n-i\) 为原字符串的一个循环。反过来推也是成立的。
那么只要check \(n-i\) 是不是循环,也就是看看存不存在一对 \(s_i=1,s_j=0\) 满足 \(i-j=k(n-i),k\in Z\)
然后构造多项式,用FFT算出所有可能的 \(i-j\),检查一下 \(n-i\) 的所有倍数就解决了。

P3565 [POI2014]HOT-Hotels

P5904 [POI2014]HOT-Hotels 加强版

若三个点两两之间的距离相等,则三条路径有且仅有一个公共点,且这个点到三个点的距离相等。枚举这个点,处理出每棵儿子子树内的信息,稍稍优化后计算即可弄到 \(O(n^2)\),通过原始版本。

把上述换根的做法转成定根的dp。转移的时候考虑以 \(u\) 作为三条路径交点,\(u\) 中子树中有 \(2/3\) 个点讨论。具体的,设 \(f_{x,i}\ \ g_{x,i}\) 表示当前遍历完的 \(subtree(x)\)\(dist(x,y)=i\)\(y\) 的数量,\(g_{x,i}\) 表示满足 \(dist(y,lca(y,z))=dist(z,lca(y,z))=dist(x,lca(y,z))+i\) 的二元组 \((y,z)\) 的数量。然后一边累加答案一边转移即可。

写出dp转移后,再用长链剖分优化至 \(O(n)\) 即可通过加强版本。

长链剖分分配空间代码:

void dp (int u, int la, int qwq) {
    int *fx = &f[dfn[u] = ++num], *fy, *gx, *gy;
    if (qwq >= 0) st[u] = qwq;
    else st[u] = id + l[u], id += l[u] + l[u];
    gx = &g[st[u]];
    fx[0] = 1; if (son[u]) dp (son[u], u, st[u] - 1);
    res += gx[0];
    for (int v : G[u]) if ((v ^ la) && (v ^ son[u])) {
        dp (v, u, -1);
        fy = &f[dfn[v]], gy = &g[st[v]];
        for (int i = 0; i < l[v]; ++i) {
            if (i) res += fx[i - 1] * gy[i];
            res += gx[i + 1] * fy[i];
        }
        for (int i = 0; i < l[v]; ++i) {
            gx[i + 1] += fx[i + 1] * fy[i];
            if (i) gx[i - 1] += gy[i];
            fx[i + 1] += fy[i];
        }
    }
}

9.27

P3688 [ZJOI2017] 树状数组

一眼看去,这不就是线段树维护矩阵(或许不用)单 \(\log\) 吗?一阵乱写,竟然 \(12\) 分。啊?这还能错?噢,原来概率不独立啊......

首先询问 \(l,r\) 就是问 \(A_{l-1},A_r\) 相同的概率是多少, \(l=1\) 需要特判。如果分别维护 \(l-1,r\)\(0/1\) 的概率然后再计算,会出问题。因为如果一个区间同时包含 \(l-1,r\),那么他们被修改的概率是相互影响的。

还是得上二维线段树,对于每个 \(l\) 维护所有 \([l,r]\) 的影响,然后分包含了 \(l-1,r\) 中的 \(0/1/2\) 个讨论,复杂度 \(O(n\log^2n)\)

其实还可以用CDQ+扫描线在复杂度不变的情况下将空间优化至线性。

3B1B 有意思的等式证明——看似没有关系答案却和Π相关

3B1B 一个具有启发性的问题

3B1B 物理碰撞模型和Π扯上关系

3B1B 物理碰撞模型和光线反射扯上关系,再到Π

9.28

P5467 [PKUSC2018]PKUSC

不是很难的计算几何问题。画个圆看看多少圆弧在多边形内就好了。

需要的技能:1、判断一个点是否在多边形内;2、求圆与线段的交点。

P6773 [NOI2020] 命运

暴力dp:\(f_{x,i}\) 表示 \(subtree(x)\) 中,没满足的条件的最大深度为 \(i\) 时的方案数。转移的时候讨论当前边 \((x,y),y\in son(x)\)\(0/1\) 即可,\(O(n^2)\)。来看看转移方程:

\(f_{x,i}=(\sum\limits_{j=0}^{i}f_{x,i}\times f_{y,j}+\sum\limits_{j=0}^{i-1}f_{x,j}\times f_{y,i})+\sum\limits_{j=0}^{deep_x}f_{x,i}\times f_{y,j}\)

括号外面的部分是填 \(1\) 的情况。

整理一下,设 \(S_{x,i}=\sum\limits_{j=0}^{i}f_{x,j}\),有

\(f_{x,i}=f_{x,i}\times(S_{y,deep_x}+S_{y,i})+f_{y,i}\times S_{x,i-1}\)

可以发现,所有 \(f_{x,i}\neq 0\)\(i\) 要么是在 \(x\) 上有限制,要么是从 \(y\) 里弄过来的,这样的 \(i\) 不会凭空增多,符合线段树合并的形式,于是可以用线段树合并来优化转移,复杂度 \(O(n\log n)\)

9.29

Day4 T4

赛时做复杂了。题目要求本质不同,把一般区间dp枚举下标改为枚举下一个值,并利用简单的贪心思想即可做到 \(O(n^2V)\)。然后发现固定一个端点不动,另一个端点每次移动只会改变一种情况,\(O(1)\) 更新即可。注意统计方案的时候要把旧的区间减去防止重复。

P6776 [NOI2020] 超现实树

分类讨论,递归处理。detail

P6630 [ZJOI2020] 传统艺能

状态设计值得一说。\(f_{x,c,0/1/2}\) 分别表示 \(c\) 次操作后,\(x\)\(fa_x\) 都没标记、\(x\)\(fa_x\) 有、\(x\) 有标记的方案数。然后分类讨论,矩阵快速幂优化。

9.30

P6765 [APIO2020]交换城市

和Kruskal重构树模板不同的是,选出的这些边不仅要让 \((x,y)\) 连通,还要让 \((x,y)\) 之间的这些东西不是一条链。如果在建立Kruskal重构树的时候对于每棵子树记录“子树内的这些边和点是否构成链”,那么只需要从 \(LCA(x,y)\) 继续往上倍增跳,跳到第一个标记为"非链"的节点,这个节点的权值就是答案。

如何判断 \(subtree(x)\) 在原图中是否构成链呢?这时候得考虑所有边,在不在重构树上的都得考虑。加入一条边 \((u,v)\),若 \(u\)\(v\) 未连通,且原来 \(u,v\) 所在连通块都是链,且 \(u,v\) 都在链的端点时,加入 \((u,v)\) 后构成一条链。其它情况都不是链。

P4451 [国家集训队]整数的lqp拆分

非常罕见地看懂了一道数学题,但其实和求斐波那契通项差不多,比较基础。记录一下比较完整的过程。对于斐波那契生成函数,有

\(F(x)=1x^1+1x^2+2x^3+3x^4\dots\)

求封闭形式:\(xF(x)+x^2F(x)+x=F(x)\rightarrow F(x)=\frac{x}{1-x-x^2}\)

然后等比数列求和:

\(G(x)=\sum F(x)^i=\frac{F(x)}{1-F(x)}=\frac{x}{1-2x-x^2}\)

将分母因式分解,并拆成两个分数之和,得到:

\(G(x)=\frac{x}{1-2x-x^2}=\frac{x}{(1-Ax)(1-Bx)}=\frac{Ax}{2\sqrt{2}(1-Ax)}+\frac{Bx}{2\sqrt{2}(1-Bx)}\ ,\ A=1+\sqrt{2},B=1-\sqrt{2}\)

发现现在两个分数的分母都是一次了,方向用等比数列求和,可以得到 \(G(x)=\sum\frac{A^n-B^n}{2\sqrt{2}}x^n\)

这个系数就是要的答案了。

10.01

P4491 [HAOI2018]染色

\(f_x\) 表示答案至少为 \(x\) 的方案数,可得 \(f_x=C_m^x\times C_n^{xS}\times\frac{(xS)!}{(S!)^x}\times(m-x)^{n-xS}\)。但其实这里的定义并不准确,它钦定了这 \(x\) 种是哪几种来计算,会产生重复。

然后设 \(g_x\) 为恰好为 \(x\) 的方案数。建立 \(f_x\)\(g_x\) 的关系 \(f_x=\sum\limits_{y=i}^m C_y^x\times g_y\),从这里也可以看出 \(f_x\) 相对于定义是有重复的。然后二项式反演,得到 \(g_x\) 的式子,使用 NTT 优化。

10.03

Day5 T4

先写出暴力的dp,若要优化,不可能再记录当前有多少糖果。考虑每次走出一个的时候都把背包塞满,用单调队列记录当前包里糖果分别来自哪里。到了一个点:

1、这段路上产生消耗,把最便宜的糖果拿来消耗

2、一些糖果在之前买的太贵了,不如现在买,把糖“退回去”

3、一些糖果先在中间某点卖掉,再在当前点买回来,可以赚差价。那就进行这次买卖。

因为用单调队列维护,这些操作都是线性的。

本题的优化总结起来就是:把这些操作集中在一点贪心考虑。

10.04

LOJ #6030. 「雅礼集训 2017 Day1」矩阵

基本策略是先把某一行全部染黑,再染所有列。然后枚举一下是哪行就完了。

Day6 T4

想歪了以为是2-SAT+拓扑计数,然后只写了暴力跑路。其实也是一种经典的连边方式,直接连边 \((a_i,b_i)\),就能得到美妙的特性了。连完边后,要做的就是给这些边定向,使得每个点入度至多为 \(1\),并且若方向为 \((b_i,a_i)\) 会产生 \(1\) 的代价。

如果这张图不是树和基环树构成的“混搭森林”,则无解,因为没法让每个点入度 \(\leq 1\)。然后对于每棵树,如果定了根(无入度的点),所有边方向就定了,可以线性dp一遍求出答案。对于基环树,不在环上的边显然指向外面,环有两种方案,比较一下也就完成了。

10.05

Day7 T3

用奇怪的二分+贪心过了。但我无法证明。第一步肯定让 \(c_i=(a_i-b_i+4)\%4\),我是这样的:

\(d_i=c_i-c_{i-1}\),然后每次操作 \([l,r]\) 就是让 \(d_l+1,d_{r+1}-1\)。从左往右扫,只有 \(1,2,3\) 三种数,分析一下然后奇怪贪心。

题解的转化稍微特殊一些,即对每个 \(c_i\) 加上 \(4\) 的若干倍(可以是 \(0\)),最后答案就是 \(\sum max(0,c_i-c_{i-1})\)。依旧令 \(d_i=c_i-c_{i-1}\),每次操作就是让 \(d_l+4,d_{r+1}-4\)。只有 \(3\)\(d_l,d_{r+1}\) 的组合能让答案更优,按照一定顺序找出来就好了。

P4457 [BJOI2018]治疗之雨

写出相互之间的关系式后直接高斯消元复杂度为 \(O(n^3)\),但发现这个矩阵非 \(0\) 的位置类似一个上三角,所以复杂度可以降为 \(O(n^2)\)

#6033. 「雅礼集训 2017 Day2」棋盘游戏

可以根据棋盘建出二分图,显然一个人是从左部点跳到右部点,另一个人跳回来。如果起点 \(x\) 可以不在最大匹配中,那么先手第一步 通过非匹配边 必然跳到匹配点,后手通过匹配边跳回来,先手又一步跳到匹配点(如果跳到非匹配点,那说明还存在增广路,不是最大匹配),后手又跳回来...最后一定是先手没路走,后手必胜。反之,如果 \(x\) 一定在最大匹配中,那么先手先通过匹配边跳一次,后手必然跳到一个匹配点(否则 \(x\) 可以被替换),然后先手再跳匹配边...最后一定是先手赢。

如何判断某个点是否必须在最大匹配中?不用把每个点去掉求一遍最大匹配,只需要先求出一组最大匹配,然后对于一个点 \(x\),如果本来就不是匹配点,那么显然不必要;否则从 \(x\) 当前匹配点出发看看能不能找到另外一条增广路,如果可以,说明 \(x\) 可被替换。还有一种方法是使用网络流然后遍历残量网络。本质上应该差不多

10.06

P1971 [NOI2011] 兔兔与蛋蛋游戏

跟上面的棋盘游戏差不多。虽然题目里没说,但其实根据奇偶性,每个点依然只能经过一次,依旧可以用二分图解决。

P6186 [NOI Online #1 提高组] 冒泡排序

\(c_i\)\(i\) 左边比 \(a_i\) 大的数量,逆序对 \(number=\sum c_i\)。每轮冒泡排序就是把每个前缀最大值(即 \(c_i=0\) 的位置)移到下一个前缀最大值的左边,除了移动的数 \(c_i=0\) 不变,其余所有数的 \(c_i-1\)。那么每次询问就是要求 \(\sum max(0,c_i-k)\),显然只需要分两类计算。每次修改只会改两个点,可以简单维护。

10.07

P6730 [WC2020]猜数游戏

若选了 \(a_i\) 后能得到 \(a_j\),则连边 \((i,j)\)。假设已经把这张图建好了,如何计算答案?先求一波强连通分量,强连通分量之间的答案贡献很好计算,现在只考虑一个强连通分量内。因为若存在边 \((i,j)(j,k)\),则必存在 \((i,k)\),所以这个强连通分量其实构成完全图,那么只需要随便给节点定个顺序即可,不妨让编号小的在前面。于是实现的时候不需要去求强连通分量,只要对于每个 \(x\) 枚举 \(y\) ,判断 \(y\) 能否到达 \(x\)。设不能从 \(y\)\(x\)\(y\) 的数量为 \(cnt\)\(x\) 对答案的贡献就是 \(2^{cnt}\)

如何判断是否存在边 \((i,j)\)

对于 \(\gcd(a_i,p)\neq1\) 的,暴力计算能到哪些 \(a_j\),因为 \(p\) 为质因数的幂次,至多 \(\log p\) 次后就变为 \(0\),所以复杂度为 \(n\log p\)

对于 \(\gcd (a_i,p)=1\) 的,显然只能走到 \(\gcd(a_j,p)=1\) 的,根据定理 \(a\equiv b \pmod p\rightarrow ord_pa=ord_pb\)\(ord_pa^k=\frac{ord_pa}{\gcd(ord_pa,k)}\),带入关系式 \(a_i^m\equiv a_j\pmod p\),可得充要条件为 \(ord_pa_j|ord_pa_i\)

如何计算 \(ord_pa_i\) ?根据 \(ord_pa|\varphi(p)\),可以试除 \(\varphi(p)\) 的素因子得到。

对于 \(\gcd(a_i,p)\neq 1\) 的,还有一种方法。设 \(p=P^m\)\(a_i=b_i\times P^{ci},\ a_j=b_j\times P^{cj}\),当且仅当 \(a_i^{\frac{cj}{ci}}\equiv a_j\pmod p\) 时存在边 \((i,j)\)

P6478 [NOI Online #2 提高组] 游戏

先树形dp \(O(n^2)\) 算出 \(g_x\) 表示选了 \(x\) 对的方案数(其它的不管)。然后设 \(f_x=g_x\times (m-x)!\) 表示钦定了 \(x\) 对的方案数。有 \(f_x=\sum\limits_{y=x}^m {y\choose x}\times ans_y\),二项式反演得到 \(ans_x=\sum \limits _{y=x}^m (-1)^{y-x}\times{y\choose x}\times f_y\),暴力算就好了。

BZOJ3640 JC的小苹果

\(f_{i,x}\) 表示还有 \(i\) 点体力,走到 \(x\) 的概率,不难写出转移 \(f_{i,x}=\sum f_{i+a_x,y}\times \frac{w_{x,y}}{deg_y}\)。由于 \(a_x\) 可能等于 \(0\),所以不能直接递推,对于每一层(每种体力)需要高斯消元,暴力消元复杂度 \((n^3 hp)\)

但事实上每一层的矩阵所有系数都是相同的,只有最后的常数不同,所以只需要一遍消元求出常数之间的贡献系数,之后每次 \(O(n^2)\) 计算即可。总复杂度 \(O(n^3+n^2hp)\)

10.08

P5996 [PA2014]Muzeum

这个问题是最大权闭合子图模型,可以利用网络流暴力求解,答案为物品价值总和减去最大流(最小割)。但数据范围大,考虑优化。\((x_i,y_i)\) 能看到 \((x_j,y_j)\) 等同于:

\(x_ih-y_iw\le x_jh-y_jw\\ x_ih+y_iw\ge x_jh+y_jw\)

不妨把 \((x,y)\) 变换为 \((xh+yw,xh-yw)\),那么条件就变为 \(x_i\ge x_j,y_i\leq y_j\)

按照 \(x\) 排序后,用贪心思想模拟网络流:每加入一个警卫节点,找 \(y\) 尽量小的手办匹配,因为 \(y\) 越大匹配范围越广。数据结构维护一下即可。

P4501 [ZJOI2018]胖

每一条出边能更新一段区间。如果能二分出区间的边界问题就解决了。注意这里不仅要考虑距离还要考虑中间经过的点数。

对于一条边 \(i\),二分边界 \(mid\),此时 \(mid\) 的答案只被 \(p_k\in[mid-|i-mid|,mid+|i-mid|]\) 的边更新过,然后要看看通过边 \(i\)\(mid\) 的距离是不是比这些 \(k\) 都小。从第 \(i\) 条边到 \(j\) 的距离:\(p_i\le j:\ l_i+d_{pi}-d_j;\ \ p_i>j:\ l_i-d_{pi}+d_j\)。那么只需分别计算 \(l_i+d_{pi},\ l_i-d_{pi}\) 的RMQ即可。

这样二分套二分复杂度为 \(n\log^2n\) 。还可以做到 \(O(n\log n)\),比如这个

P3214 [HNOI2011]卡农

如果没有不重复的条件,显然可以对每个二进制位来考虑。但这题直接按照个数来递推。

\(f_i\) 表示选 \(i\) 个元素的可行方案数。所有方案为 \((_{i-1}^{2^n-1})\),因为选了前 \(i-1\) 个最后一个就定了;为了不让新选的这个为 \(0\),前 \(i-1\) 个不能为 \(0\),减去 \(f_{i-1}\);为了不出现重复,即前 \(i-2\) 个为 \(0\),减去 \(f_{i-2}\times((2^n-1)-(i-2))\);最后,因为算的是无序的方案数,上述过程会把每种算 \(i\) 次,应除掉 \(i\)。得到 \(f_i=\frac{(_{i-1}^{2^n-1})-f_{i-1}-f_{i-2}\times((2^n-1)-(i-2))}{i}\)

预处理一下可以做到 \(O(m)\)。如果嫌预处理组合数麻烦,可以先转成计算有序集合的数量,这样只用预处理排列数,最后再除掉 \(m!\)

P6830 [IOI2020]连接擎天树

\(p\) 很小,直接对 \(p\) 分类讨论:

\(p_{x,y}=1\),把所有这样的 \((x,y)\) 在并查集中合并,若连通块内存在 \(p\ne1\) 则无解。否则随便构造一棵树即可。

\(p_{x,y}=2\),把这样的 \((x,y)\) 在另一个并查集中合并,若连通块内存在 \(p\ne2\) 则无解。对于大小为 \(2\) 的连通块同样无解。否则随便构造一个环即可。

\(p_{x,y}=3\),若出现就无解。因为至少存在一对 \(p_{x',y'}>3\),不符合题目限制。

P6831 [IOI2020]嘉年华奖券

如果每一轮选定了 \(n\) 张奖券,那么主办方选中位数,价值就是前 \(\frac{n}{2}\) 大的减去前 \(\frac{n}{2}\) 小的。考虑颜色 \(i\) 选出的 \(k\) 张,其中 \(small_i\) 张充当了小的那部分,\(big_i=k-small_i\) 次充当了大的部分,显然一定是选了最小的 \(small_i\) 张和最大的 \(big_i\) 张。初始先让 \(\forall i,small_i=k\),然后进行 \(\frac{nk}{2}\) 次调整,每次让一个 \(small_i-1,big_i+1\),并且每次都选利益最大的那个调整,这个过程可以用堆维护。

假设调整完后得到的答案是 \(res\),原问题的答案是 \(ans\),不难发现 \(res\ge ans\),而且一定可以构造出一种方案(根据上述贪心过程),所以 \(res=ans\)。构造方案的时候似乎不需要贪心,直接把 \(big\) 的从 \(1\)\(k\) 循环着往里面填就好了 ,code

P4983 忘情

要把长度为 \(n\) 的分成 \(m\) 段,且明显段数越多越优,考虑WQS二分:二分一个每段的额外代价 \(C\),找到 \(C'\) 使得最优解 \(ans\) 恰好要用 \(m\) 段,答案就是 \(ans-mC'\)。对于每次二分,有转移方程 \(f_i=\min\{f_i+(s_i-s_j+1)^2+C\}\),是一个可以斜率优化的形式:若 \(j\) 优于 \(k\),则 \(s_i>\frac{(f_j+s_j^2-2s_j)-(f_k+s_k^2-2s_k)}{2(s_j-s_k)}\),且 \(s_i\) 单增,所以单调队列维护一个凸壳即可。

CF888G Xor-MST

首先,对于权值相同的点,显然可以不花钱就缩成一团。现在没有权值相同的点了。

把这些权值插入\(\text{trie}\)树,在叶子 \((x,y)\) 间连边,只需考虑 \(LCA(x,y)\) 之下的部分。因为权值都不相同,所以恰好有 \(n-1\) 个可以成为 \(\text{LCA}\)的点,在这些点贪心地连一条跨越左右儿子子树的边就构成了最小生成树。

具体贪心:从左右儿子出发,每次尽量走同一个儿子,如果两边都有就都走,取 \(\min\);如果走不了同一个儿子,就得加上这一层的权值,然后继续向下。注意到在贪心的过程中,有可能两边都要走,复杂度对吗?对每个叶子 \(x\) 考虑,走到一次 \(x\) 复杂度为 \(\log V\),而 \(x\) 上方至多 \(\log V\) 个点需要连边,所以复杂度为 \(O(n\log^2V)\)

还可以启发式合并trie树来处理,但应该没上面的做法简洁。

10.09

CF1481E Sorting Books

被移动的书顺序随意,但没有动的书顺序固定,且必须同色连成一块,所以对没动过的书进行dp。设 \(f_i\) 为后缀 \([i,n]\) 中至多保留多少。考虑第 \(i\) 本书。

  1. \(i\) 是颜色 \(a_i\) 的左端点,保留所有 \(a_i\),则 \(f_i\leftarrow cnt_{ai}+f_{r_{ai}+1}\)
  2. \(i\) 不是右端点,但仍要保留后缀 \([i,n]\) 中的 \(a_i\),那么后缀 \([i,n]\) 中其它的颜色都必须移动,则 \(f_i\leftarrow cnt_{ai}\)。这里的 \(cnt_{ai}\) 指后缀 \([i,n]\)\(a_i\) 个数。
  3. 移动 \(i\)\(f_i\leftarrow f_{i+1}\)

P4425 [HNOI/AHOI2018]转盘

如果从起点开始往后走,中间可能会停下来等待物品出现,不容易想清楚。不妨倒过来,考虑终点在 \(t\),每次往前走一步,物品会在 \(T_i-1\) 消失,那么马不停蹄一直走最优。(把环拆开复制一遍)不难得到答案为 \(\max\limits_{i=t-n+1}^t(T_i+t-i)\)

写完整并稍微变换可以得到 \(res=\min_{s=1}^n(s+\max_{i=s}^{2n-1}(T_i-i))+n-1\)。这里改成了枚举起点 \(s\),并且 \(i\) 的上界改为 \(2n-1\),因为后面那些不影响答案。

其中 \(\max_{i=s}^{2n-1}(T_i-i)\) 表示后缀最大值。可以用单调栈求出对于每一个 \(j\)\(T_j-j\) 是后缀 \([s,2n-1]\) 最大值的 \(s\) 的范围。现在的问题就是动态维护这个单调栈。

用线段树来搞。合并左右子树的时候,右边的单调栈保留;对于左边,在线段树上二分右边最大值在左边“侵占”的位置,更新一下答案。复杂度 \(O(n\log^2 n)\)

P6624 [省选联考 2020 A 卷] 作业题

先对原式进行欧拉反演,得到:\(val(T)=(\sum w_{ei})\times \sum\limits_{p|w_{e1},p|w_{e2}\dots}\varphi(p)\)

\(\varphi(p)\) 提前,得到:\(\sum \varphi(p)\times (\sum w_{ei})\),这里的 \(w_{ei}\) 只剩下 \(p\) 的倍数。

然后枚举 \(p\),后面的部分可以使用矩阵树定理计算。具体的,在矩阵的每个位置记录一个二项式 \(w_ix+1\),对二项式进行运算求行列式,一次项系数即为答案。

关于行列式、矩阵(线性代数)内容的深入学习还是等NOIP后吧。

P5540 [BalkanOI2011] timeismoney | 最小乘积生成树

这个做法比较奇怪,适用性应该也不广。但还是记录一下吧。

\((\sum a,\sum b)\) 弄到坐标轴上,每个点代表一种生成树方案。找到离 \(x,y\) 轴最近的点 \(A,B\)(可以直接求最小生成树), \(C\)\(A,B\) 更优的必要条件是 \(C\)\(AB\) 下方。找到在 \(AB\) 下方的离 \(AB\) 最远的点 \(C\)(列一下式子,同样可以直接求一遍最小生成树得到),递归处理 \(CA,CB\)。一直递归下去直到直线下方空空如也。感性理解复杂度不会太高。

CF1479B2 Painting the Array II

\(f_{i,j}\) 表示处理了前 \(i\) 个,一个序列的末尾是 \(i\),另一个是 \(j\) 时答案的最小值。有转移:

\(f_{i,j}\leftarrow f_{i-1,j}+[a_i\ne a_{i-1}];\ \ f_{i,a_{i-1}}\leftarrow f_{i-1,j}+[a_i\ne j]\)

然后发现,第一个转移就是整体 \(+1\),用一个变量记录即可;第二个转移就是单点修改,同样可以快速完成。复杂度优化至 \(O(n)\)

值得一提的是这题还可以贪心。直接维护这两个数列,将 \(a_1,a_2,a_3\dots a_n\) 依次加入,若 \(a_i\) 和其中一个数列的尾部相同,就加入这一个;否则,设 \(next\) 为 和数列尾部相同的 下一个数的位置,将 \(a_i\) 加入 \(next\) 较大的数列。正确性不难理解

P7323 [WC2021] 括号路径

如果 \((x,y)(y,z)\) 合法,则 \((x,z)\) 合法,这样的关系形成团。那么就是要把它们合并在一起。

对于每个点用一个 \(\text{map}\) 记录每种颜色出边的另一端,若存在多个点可以合并在一起,所以只需要记录一个。

初始的时候,遍历所有边,建出 \(\text{map}\),若在过程中需要合并 \((x,y)\),先在并查集里合并,但不合并边的信息,只是把 \((x,y)\) 扔进一个队列。然后,类似于 \(\text{bfs}\) 拓展的过程,每次取出队首,启发式合并边的信息,然后把新的要合并的若干 \((x',y')\) 加入队尾,直至队列为空。根据并查集里的连通性信息就可以算出答案了。

为什么要先加入一个队列,而不能当场合并呢?其实也可以,这相当于把 \(\text{bfs}\) 变成了 \(\text{dfs}\),再把队列改成栈就可以达到一样的效果。

启发式合并+\(\text{map}\) 复杂度为 \(O(n\log k\log n)\),已经可以通过此题。若把 \(\text{map}\) 改成 \(\text{hash}\)表或者 \(\text{unordered\_map}\),可以降一个 \(\log\);当然也可以用线段树合并换掉启发式合并,同样少一个 \(\log\)

P4640 [BJWC2008]王之财宝

\(T\) 小,暴力容斥,枚举不符合限制的物品集合 \(S\),有 \(ans=\sum(-1)^{|S|}f(S)\)\(f(S)\) 直接插板法计算即可,需要用到 \(\text{Lucas}\)定理:\({n\choose m} \equiv {m/p\choose n/p}\times{m\%p\choose n\%p}\pmod p\)

P5504 [JSOI2011] 柠檬

不难发现,最优情况下,每段的两端一定相同,而且每段所选的 \(s_0\) 就是两端贝壳的大小。否则可以缩小当前区间而价值不变,却多出另一段,总和更大。

\(f_i\) 为前缀 \([1,i]\) 的答案,有 \(f_i=\max\limits_{1\le j\le i,s_i=s_j}\{f_{j-1}+s_i\times (c_{i,si}-c_{j-1,si}+1)^2\}\)

按照一般做法,这个式子可以通过斜率优化快速计算。这里记录另一种优化方法。

后面那部分可以看作二次函数,随着 \(j\) 减小递增,且斜率越来越大(只考虑 \(s_i=s_j\) 的位置)。所以若 \(j_1<j_2\),且当前 \(j_1\) 更优,那么之后一直是 \(j_1\) 优于 \(j_2\)。而且 \(j_1\) 首次优于 \(j_2\) 的时刻可以二分得到。

具体的,对每种贝壳维护一个栈,设栈顶元素为 \(top\),下一个元素为 \(top-1\),加入元素 \(x\) 时,二分出 \(top\) 首次优于 \(x\) 的时间 \(t\):若 \(t\) 早于当前时刻,不用加入;若 \(t\) 迟于 \(top-1\) 首次超过 \(top\) 的时间 \(t'\),弹出栈顶,重复此过程\(\dots\),这样栈顶记录的就是最优解了。复杂度比斜率优化多出一个 \(\log\)

10.10

P3358 最长k可重区间集问题

先把题目转换成:选 \(k\) 次,每次选若干不相交的区间,不能重复选,使长度和最大。然后就可以网络流了。

把区间的端点拿出来,排序离散化。连以下几种边:

1、由源点向第一个点连边 \((V=k,cost=0)\),表示可选 \(k\) 次。

2、第 \(i\) 个点向第 \(i+1\) 个点连边 \((k,0)\),表示若不相交可以同时选。最后一个点连向汇点。

3、在每个区间的 \(l_i,r_i\) 之间连边 \((1,r_i-l_i)\),表示只能选一次,价值为 \(r_i-l_i\)

对此图求出最大费用最大流即可。

P1251 餐巾计划问题

把一天形象的拆成白天和黑夜两个节点,连以下边:

1、源点向每个夜晚连边 \((V=a_i,cost=0)\),表示一天结束会留下 \(a_i\) 条脏餐巾

2、白天向汇点连边 \((a_i,0)\),因为最终这些边一定满流,相当于限制每天都得有 \(a_i\) 条干净的。

3、从每个夜晚向下一个夜晚连边,表示脏的留着不洗;第 \(x\) 个夜晚向第 \(x+n/m\) 个白天连边,表示洗干净;源点向每个白天连边,表示新买餐巾。

对此图求最小费用最大流即可。

本题的关键在于把一天拆成两点,白天流出,夜晚补入,既限制了每天要有 \(a_i\) 条餐巾,又将脏餐巾保留了下来。

P3355 骑士共存问题

把棋盘黑白染色,会相互攻击的位置颜色不同。那么把相互攻击的关系用边表示,得到的是二分图,要求的就是二分图最大独立集,根据定理有 最大独立集\(=\)点数\(-\)二分图最小点覆盖\(=\)点数\(-\)二分图最大匹配。所以只要求二分图最大匹配。
P2766 最长不下降子序列问题

先用入门dp算出 \(f_i\) 表示以 \(a_i\) 结尾的最长序列。在所有长度为 \(s\) 的方案中,\(a_i\) 都只能被放在第 \(f_i\) 个。所以可以建出分层图,在相邻层之间连边,合理设置边的容量,算最大流即可解决第二、三问。

P1452 [USACO03FALL]Beauty Contest G /【模板】旋转卡壳

先求出凸包,最远点对一定可以被一对平行卡壳卡住(称为对踵点),可以枚举对踵点来计算。

具体实现时,把卡住两点改成卡住一边一点,将点和边的两端分别计算,这样效果不变,运算简单。顺时针枚举边,另一个点显然就是距离这条边最远的点,而且这个点同样顺时针旋转,于是可用双指针可做到 \(O(n)\)。但要先求凸包,总复杂度 \(O(n\log n)\)

10.11

AT1219 歴史の研究

方案Ⅰ:使用普通莫队,问题变成了 \(O(n\sqrt{n})\) 次插入、删除,\(O(n)\) 次询问最值。为了不让 \(n\sqrt{n}\) 再带上 \(\log\),通常用值域分块维护答案。

本题答案可能极大,不能直接分块。但不难发现答案其实只有 \(O(n)\) 种,离散化后再值域分块即可,复杂度 \(O(n\sqrt{n})\)

方案Ⅱ:如果只有插入操作,询问最值,就不需要数据结构维护了。由此想到采用回滚莫队,操作次数仍是 \(O(n\sqrt{n})\),每次只要 \(O(1)\)\(\max\) 或者撤销操作即可。

回滚莫队具体实现:先分块,询问的排序方式不变,把 \(l\) 在同一块中的一起处理。每次询问先把左指针指在 \(l\) 所在块的右边界,然后向左移动到 \(l\),而 \(r\) 在同一块中单调,右指针一路向右扫,只加不减。每次先移右指针再移左指针,存储左指针移动带来的变化,询问完后即时撤销。

P6619 [省选联考 2020 A/B 卷] 冰火战士

随着温度升高,一个函数单调递增,一个函数单调递减,两条线取 \(\min\),当然在交点处最大。若直接在线段树上二分,复杂度为 \(O(n\log n)\)。这些都是很容易想到的,但是被卡常了,本题需要在树状数组上二分。

具体的,初始二分边界 \(l=1,r=2^k\),右边界设为 \(2^k\) 是为了让 \(tree_{mid}\) 存储的刚好是 \([l,mid]\) 的和。然后就可以快速二分了。

P2447 [SDOI2010]外星千足虫

若能解出所有未知数,需要至少 \(n\) 个相互独立(不能相互推得)的方程。把每个方程看成一个二进制数,就等价于 不能通过其他数异或得到。这个问题当然用线性基解决,使用 \(\text{bitset}\) 优化后复杂度为 \(O(\frac{n^3}{w})\)

P6628 [省选联考 2020 B 卷] 丁香之路

将原题转化为:图中初始有 \(m\) 条边,需要添加若干条边,使得所有度数不为 \(0\) 的点、 \(s、t\) 连通,且存在从 \(s\)\(t\) 的欧拉路,求添加边的最小长度和。

欧拉路的条件是 \(s,t\) 的度数为奇,其余为偶。从左到右遍历 \(x\),若 \(x\) 度数不满足条件,则连边 \((x,x+1)\)。这些边代价都为 \(1\) 且不相交,所以花费最小,同时尽量减少了连通块个数。

然后用最小生成树来保证连通性。因为本题边权特殊,考虑相邻两点之间的边即可。为了维持度数奇偶性,新加的树边都要两条。

两步处理完得到的就是最优解了。上述过程保证了添加的非必经边不相交,感性理解正确性可以保证。复杂度为 \(O((m+n^2)\log n)\)

P6622 [省选联考 2020 A/B 卷] 信号传递

拆拆拆!把路径的代价拆出来分别计算,就可以暴力状压dp了。然后递推预处理优化到 \(O(m2^m)\)。然而这题的重点在于卡空间

P2597 [ZJOI2012]灾难

如果能根据支配关系建出一棵树,问题就解决了。\(x\) 的支配点是所有 \(x\) 前驱节点在支配树上的 \(\text{LCA}\)。只要在拓扑排序时顺带着计算即可。

P1912 [NOI2009] 诗人小G

和 10.09-P5504 [JSOI2011] 柠檬 如出一辙的决策单调性优化,这类题目的\(\text{dp}\)转移式中都有一个斜率单调的函数,比如常见的幂函数。

P4965 薇尔莉特的打字机

一眼看去以为是要在 \(\text{trie}\) 上搞了,但其实只要“假装有一棵trie树”,然后计数就行。\(f_i\) 的定义不是很好想。

具体的,设 \(f_i\) 表示没有儿子 \(i\) 的 可拓展的 节点数。原字符串在树上构成链,一开始只有最后一个点可拓展。

加入字符 \(x\),新增 \(f_x\) 个节点,把除了 \(f_x\) 之外的 \(f_i\) 都加上 \(f_x\)

删除 \(x\),初始链上多出一个可拓展的点,给除了原有的一个儿子外 \(f_i+1\)

复杂度 \(O(26n)\)

10.12

BZOJ4544 椭圆上的整点

移项得到 \(3y^2=r^2-x^2=(r+x)(r-x)\),令 \(d=\gcd(r+x,r-x),A=\frac{r+x}{d},B=\frac{r-x}{d}\),原式变为 \(3y^2=A\times B\times d^2\)

\(3y^2\) 为完全平方的 \(3\) 倍,\(d^2\) 为完全平方,那么 \(A,B\) 其中一个为完全平方,另一个为完全平方的 \(3\) 倍,且 \(\gcd(A,B)=1\)。设 \(A=3a^2,B=b^2\),有 \(A+B=3a^2+b^2=\frac{2r}{d}\)

先枚举 \(d\),然后枚举 \(a\),判断是否存在 \(b\)\(\gcd(A,B)=1\),统计答案即可。复杂度和 \(2r\) 的约数个数有关,假设约数个数为 \(\sqrt{2r}\),复杂度上界为 \(O(\sum_{i=1}^{\sqrt{2r}}(\sqrt{i}+\sqrt{\frac{2r}{i}})=\sum_{i=1}^{\sqrt{2r}}\sqrt{i}+\sqrt{2r}\sum_{i=1}^{\sqrt{2r}}\frac{1}{\sqrt{i}})=O((\sqrt{2r})^{1.5})=O(r^{0.75})\)。当然这是远远不满的。

P2508 [HAOI2008]圆上的整点

显然可以用和上一题一样的方法解决。但本题有更奇妙更优秀的做法。

把问题搬到复数域里,\(a^2+b^2=r^2\rightarrow (a+bi)(a-bi)=r^2\),问题变成了求 有多少个高斯整数(\(a,b\) 为整数的复数) \(Z\) 满足 \(Z\times\overline{Z}=r^2\)

类比于整数域的质因数分解,复数域同样可以“素数分解”。若高斯整数 \(p\) 不能被表示为若干高斯素数的乘积,则称 \(p\) 为高斯素数。

如何判断一个数是否为高斯素数?使用费马平方和定理:奇素数可以表示为两个正整数的平方和,当且仅当 \(p\equiv 1 \pmod 4\),且方案唯一。(可表示为两个正整数平方和 与 \(p+0i\) 不是高斯素数等价)

铺垫结束。把 \(r^2\) 在整数域内质因数分解:\(r^2=2^n\prod\limits_{A_j=4k+1} A_j^{p_j}\prod\limits_{B_j=4k+3}B_j^{q^j}\),分类讨论:

对于非高斯素数 \(A_j+0i\),可以拆成 \(z_j,\overline{z_j}\),必须一个分给 \(Z\),一个分给 \(\overline{Z}\)。和计算约数个数时一样,\(Z\) 可以得到 \(0,1,2\dots p_i\)\(z_j\),所以对答案的贡献为 \(p_j+1\)

对于无法分解的高斯素数 \(B_j+0i\),必须给 \(Z,\overline{Z}\) 分配相同个数的 \(B_j\)。所以若 \(2|q_j\),仅存在一种方案;否则答案为零。

对于 \(2^n\)\(2+0i=(1+i)(1-i)\),看似和 \(A_j\) 是同类的,但 \(1+i,1-i\) 的夹角是 \(90^{\circ}\),旋转后并不能产生更多的答案,不用去管。(答案 \(a+bi\)\(a-bi,b+ai,b-ai\) 成对出现,已经 \(\times 4\) 了,别重复计算)

分解 \(r^2\) 只需分解 \(r\),复杂度为 \(O(\sqrt{r})\)

CF613D Kingdom and its Cities

每次询问选 \(k\) 个点进行,明摆着要建虚树。

虚树的建立:用栈维护最新的一条树链,把 \(k\) 个点按 \(dfs\) 序排序后依次加入:若栈为空,直接加入 \(x\);否则,取 \(lca=LCA(u,stk[top])\),若 \(lca=stk[top]\),树链继续延长,直接加入 \(x\);否则,出现分叉,把 \(lca\) 之下的这段树链连边并弹出,然后加入 \(lca,x\)

接下来简单地\(\text{dp}\)一下即可。

P1654 OSU!

三次的期望和不等于期望和的三次。要从一次推到二次,二次推到三次。

P2260 [清华集训2012]模积和

复习一下整除分块:对于 \(i\le n\),最大的 使得 \(\lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor\) 成立的 \(j=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)。每次把 \([i,j]\) 一起计算,然后让 \(i=j+1\)。因为 \(\lfloor\frac{n}{i}\rfloor\) 最多有 \(2\sqrt{n}\) 种取值,复杂度为 \(O(\sqrt{n})\)

之后就简单了,先把 \(i\neq j\) 的限制扔到后面,得到 \(\sum_{i=1}^n(n\%i)\times\sum_{i=1}^m(m\%i)-\sum_{i=1}^{\min(n,m)}(n\%i)\times(m\%i)\)

然后把 \((n\%i)\) 都写成 \(n-i\times \lfloor\frac{n}{i}\rfloor\),前面乘号两边的式子直接整除分块计算,后面的先把括号拆开再计算。

CF452F Permutation

把问题转移到 \(a\) 的逆序列 \(b\)\(b_{ai}=i\))上,问题变成是否存在 \(b_{x-t}<b_x<b_{x+t}\)。枚举 \(x\),定义 \(c_p=[b_p<b_x]\),那么只要看看从 \(x\) 开始向两边延伸的\(0/1\)串是否相等。

这提示我们利用哈希:如果按照 \(b_x\) 大小顺序来枚举 \(x\),每次只会改变一个 \(c_p\),用线段树维护\(0/1\)串的哈希值比较一下即可。

10.13

CF1406E Deleting Numbers

暴力做法:枚举每个质数 \(p\),执行一次删除 \(p\),然后询问 \(p,p^1,p^2\dots\),看看 \(x\) 含有 \(p\) 的几次。

基于 \(x\) 至多含有一个 \(>\sqrt{n}\) 的素因子,可以进行根号分治。定义 \(\ge\sqrt{n}\) 的质数为小素数,其余为大素数。

对于所有小素数执行暴力做法,此时集合中只剩下 \(1,x\) 和所有大素数。

\(x\) 为合数,并且含有 \(\ge \sqrt{n}\) 的因子 \(P\),那么当且仅当询问 \(P\) 时答案为 \(2\),对于所有大素数询问一次即可。

\(x\) 为大素数,似乎又要执行暴力做法了。但这时可采用分块优化,删除 \(B\) 个后再询问一次 \(1\),看看 \(x\) 在不在其中,如果在这 \(B\) 个里,暴力这 \(B\) 个,否则继续检查后面的 \(B\) 个。询问次数成功开平方。

P5610 [Ynoi2013] 大学

一个朴素的想法:用 \(5\times10^5\)\(\text{set}\) 维护每个数倍数的所有下标,修改的时候在对应 \(\text{set}\) 中遍历区间内的元素。一个元素被修改的时候不需要马上修改与之相关的 \(\text{set}\),下次用到的时候再判断即可。

这样做显然过不了 \(\text{Ynoi}\)。上述的 \(\text{set}\) 只删不加,杀鸡焉用牛刀,可以换成 \(\text{vector}\) + 并查集:\(\text{vector}\) 替换 \(\text{set}\),并对每个容器维护一个并查集,删除 \(x\) 的时候,在并查集上将 \(x\) 并入后一个元素。其实并查集中 \(fa_x\) 记录的就是 \(x\) 之后第一个未被删除的元素。

像这样仅在一个序列上合并的并查集复杂度为 \(O(\alpha(n))\),而一个数最多被删除 \(\log V\) 次,这部分是 \(O(n\log V\alpha(n))\)。还要用树状数组维护区间和,\(O(n\log V\log n)\)。应该跑不满,卡卡常可过。

CF611H New Year and Forgotten Tree

对于每种位数钦定一个“核心点”。任何一种方案都可以转化为 没有两个非核心点相连 的情况。

核心点数量只有 \(6\),那么核心点之间的连边可以爆搜出来。对每一种寻找方案。

根据定义,任意一个非核心点 \(x\) 的度数为 \(1\)(若 \(>1\) 必成环),只能匹配一条边。

1、对于同种位数的连边,只能匹配一种点。这部分先处理掉。

2、对于不同位数间的连边,需从两种点中选一种匹配。这显然是一个网络流模型,建出图跑一遍最大流看看流量是否正确。如果可行遍历残量网络找出方案。

CF627E Orchestra

枚举左上角然后使用尺取法复杂度为 \(O(r^2c)\)。注意到 \(k\) 很小,把重心放到有点的这些位置上。

按照以 列、行 分别为第一、二关键字的顺序,用链表维护所有点,并对每个点记录之后第 \(k-1\) 个点所在的列。然后枚举上边界 \(U\),下边界 \(D\rightarrow D-1\) 时,需要从链表中删除这一行的点,每次删除只会影响前 \(k\) 个位置,暴力修改即可。在修改的时候可以顺便维护左右边界方案数的变化。复杂度为 \(O(rnk)\)

P3287 [SCOI2014]方伯伯的玉米田

“修改一段区间”可以改成“修改一段后缀”,那么就可以 \(dp\) 了:设 \(f_{i,j}\) 表示第 \(i\) 个数加了 \(j\),以 \(a_i\) 结尾的最长序列。如果把 \((j,a_i+j)\) 扔到二维平面上,转移的时候就是要求左下方元素的最大值,使用二维树状数组维护。

51nod 1317 相似字符串对

要满足 \(A+C=C+B=S\),若存在 \(C\),必定能够让 \(|C|<n\),否则 \(S\) 的前面一段是若干个 \(A\),可以删掉只留一个。

\(D=S[|C|+1,n]\),原条件可以转化为存在 \(C,D\),使得 \(A=C+D,B=D+C\)。对于每个 \(A\),设其最小循环节长度为 \(m\),那么只能得到 \(m\)\(B\)

于是设 \(f_i\) 表示最小循环节长度为 \(i\) 的字符串数量,容斥可以得到 \(f_i=k^i-\sum_{j|i}f_j\)\(answer=\sum f_i\times i\)\(n\) 的因数很少,暴力算就好了。

10.14

P3179 [HAOI2015]数组游戏

\(\text{SG}\)函数基本内容:把博弈游戏转化到有向图上,每个节点代表一个状态。\(SG(x)=mex\{S\}\),其中 \(S\)\(x\) 的后继节点\(SG\)值集合。假设游戏起点集合为 \(P\)\(V=SG(x_1)\oplus SG(x_2)\oplus\dots\oplus SG(x_k),x_i\in P\),当且仅当 \(V\ne0\) 时先手必胜。

举个例子,对于 \(Nim\) 石子游戏,可以把每堆石子上进行的过程看成一张有向图。设节点 \(x\) 代表剩了 \(x\) 个式子的状态,这张图形态特殊,\(x\) 向所有 \(y<x\) 连边,所以 \(SG(x)=x\)。一共有 \(n\) 堆式子,每堆石子的起点为 \(a_i\),令 \(V=SG(a_1)\oplus SG(a_2)\oplus\dots\oplus SG(a_n)=a_1\oplus a_2\oplus\dots\oplus a_n\),当且仅当 \(V\ne 0\) 时先手必胜,这就得到了广为人知的经典结论。这是最简单的应用,使用\(\text{SG}\)函数还可以对各种复杂变式轻松处理。

对于本题中的翻棋子游戏,同样可以转化到有向图上使用\(\text{SG}\)函数。如果把 \(n\) 个棋子一起考虑,状态显然过于复杂。尝试通过一定的转化把每个棋子独立出来。

类比于上面的 \(Nim\) 石子游戏,把第 \(x\) 个棋子(只考虑白的)看成大小为 \(x\) 的石堆,令 \(V\) 为所有石堆大小的异或值。若翻转了 \(x,2x,3x\dots kx\)\(V\rightarrow V\oplus x\oplus 2x\oplus\dots\oplus kx\),相当于删除了大小为 \(x\) 的石堆,加入大小为 \(2x,3x\dots kx\) 的石堆。

这样一来每个棋子都成了一个独立的游戏,根据\(\text{SG}\)定理,有 \(SG(x)=mex\{0,SG(2x),SG(2x)\oplus SG(3x),SG(2x)\oplus SG(3x)\oplus SG(4x),...\}\),最终答案为白棋子位置 \(SG\) 值的异或和。

不难发现,\(\lfloor\frac nx\rfloor=\lfloor\frac ny\rfloor\rightarrow SG(x)=SG(y)\),于是可以进行整除分块只计算 \(\sqrt{n}\) 个位置,计算每个位置时再次分块,利用异或前缀和计算答案。

复杂度为 \(O(\sum_{i=1}^{\sqrt{n}}(\sqrt{i}+\sqrt{\frac{n}{i}})=\sum_{i=1}^{\sqrt{n}}\sqrt{i}+\sqrt{n}\sum_{i=1}^{\sqrt{n}}\frac{1}{\sqrt{i}})=O((\sqrt{n})^{1.5})=O(n^{0.75})\)

P4318 完全平方数

转化为二分+判定。判定就是要求出 \([1,n]\) 内有多少数符合要求。直接容斥,用总数量\(-\)含至少奇数个质数的平方因子的数量\(+\)含至少偶数个质数的平方因子的数量。根据 \(\mu(x)\) 的性质,正好可以把它作为系数,得到答案为 \(\sum_{i=1}^{\sqrt{n}}\mu(i)\times\lfloor\frac{n}{i^2}\rfloor\)

CF1139D Steps to One

使用公式 \(E(X)=\sum P(X\ge i)\),接下来要求出 \(P(X\ge i)\),等价于求 \(P(X<i)\),也就是要求长度为 \(i-1\)\(\gcd=1\) 的序列数。这个问题和上面的P4318十分类似,同样使用 \(\mu(x)\) 作为系数进行容斥:\(\sum\mu(j)\lfloor\frac{m}{j}\rfloor^{i-1}\)

于是有 \(E(X)=1+\sum_{i\ge2}\frac{m^{i-1}-\sum_{j=1}^m\mu(j)\lfloor\frac{m}{j}\rfloor^{i-1}}{m^{i-1}}=1-\sum_{i\ge2}\frac{\sum_{j=2}^m\mu(j)\lfloor\frac{m}{j}\rfloor^{i-1}}{m^{i-1}}\)

调整枚举顺序:\(1-\sum_{j=2}^m\mu(j)\sum_{i\ge1}(\frac{\lfloor\frac mj\rfloor}{m})^i\)

套用公式 \(\sum_{i\ge1}x^i=\frac{x}{1-x}\ (x<1)\) 得到 \(1-\sum_{j=2}^m\mu(j)\frac{\lfloor\frac mj\rfloor}{m-\lfloor\frac mj\rfloor}\)。干就完了。

BZOJ4977 跳伞求生

根据网络流图的特殊性质优化暴力费用流(模拟费用流)。

先将队友和敌人放在一起按弹药数排序,若相同让队友在前面。然后依次处理队友 \(i\),其贡献为 \(a_i-b_j+v_j\)。根据最简单的贪心思想,用堆维护 \(-b_j+v_j\) 的最大值,把它匹配给 \(i\)

但在网络流模型中,局部最优显然无法推出全局最优,所以还要模拟费用流的“反悔”操作。具体的,匹配了 \((i,j)\) 后,将 \(-b_j+v_j\) 弹出,加入 \(-a_i\)。如果 \(i'\) 选了 \(-a_i\),相当于用 \(i'\) 换掉 \(i\),反悔了 \((i,j)\) 的匹配。

执行以上“可反悔(替换)贪心”的效果等同于费用流。

一顿操作有些迷。不禁想问:怎样的模型可用模拟费用流优化呢?观察上面的表达式,\(i,j\) 对于匹配的价值的贡献相互独立,所以可用堆来维护部分价值的最优解。

LOJ6089. 小 Y 的背包计数问题

对于体积 \(>\sqrt{n}\) 的物品,肯定用不完,可以看成完全背包。如果暴力计算复杂度为 \(O(n^2)\)。换一种方式填充:每次往背包里加入一个大小为 \(\lceil\sqrt{n}\rceil\) 的物品,或让背包里物品体积都 \(+1\)。设 \(g_{i,j}\) 表示有 \(i\) 个物品,总体积为 \(j\) 的方案数,然后递推。因为至多用 \(\sqrt{n}\) 个物品,复杂度为 \(O(n\sqrt{n})\)

对于前 \(\sqrt{n}\) 种物品,将多重背包计数转化成完全背包:先按照完全背包递推一遍,然后减去不符合限制的方案数。只需倒序枚举 \(j\),令 \(f_{i,j}-f_{i,j-(i+1)\times i}\)

两种都算完后 \(O(n)\) 合并起来就是最终答案。

10.15

BZOJ5003 与链

拆开考虑二进制下每一位的权值 \(2^p\),根据图的性质,如果 \(2^p\) 的数量定了,那么方案唯一。

现在问题变成了:有 \(p\) 种物品,第 \(p\) 种价值为 \(2^p\),有 \(k\) 个,求选取若干物品使得总价值为 \(n\) 的方案数。

和上一题LOJ6089中 \(\le \sqrt{n}\) 的物品的处理一样,先求完全背包的方案数,然后减去超过限制的部分,复杂度为 \(O(n\log n)\)

P6623 [省选联考 2020 A 卷] 树

\(x\) 处合并 \(y\in son(x)\) 的答案时,需要:加入 \(v_x\);合并 \(son(y)\) 内的数;给所有数\(+1\);查询异或和。

使用\(\text{trie}\)树维护答案,除了全局 \(+1\) 之外都是常规操作。\(+1\) 会导致从低位到高位的进位,那么把\(\text{trie}\)从低位到高位倒着建(反正不求最值)。\(+1\) 在这一位的影响等同于交换 \(0/1\) 儿子,还要考虑进位:在交换前权值为 \(1\) 的子树里继续向下递归修改。

单次\(+1\)修改修改复杂度为 \(\log V\)\(\text{trie}\) 合并复杂度为 \(n\log V\),总复杂度 \(O(n\log V)\)

其实还可以找规律+差分

P6097 【模板】子集卷积

\(FWT\) 可以解决 \(i|j=k\) 的限制。对于 \(i\&j=0\),转化为 \(pop\_count(i)+pop\_count(j)=pop\_count(k)\)。那么把下标 \(i\) 分到第 \(pop\_count(i)\) 组,在符合要求的两组间进行 \(FWT\),就同时满足了两个条件。

P3822 [NOI2017] 整数

结论:如果对一个二进制数多次执行高精度\(+1\),暴力进位,每次均摊复杂度为 \(O(1)\)。回到本题,每次加一个有 \(\log|a|\)\(1\) 的二进制数,如果暴力进位计算,复杂度为 \(O(n\log|a|)\)

但如果有加有减,复杂度没有保证,所以只能分别维护加、减的总和 \(A,B\)。询问 \(k\) 的时候要考虑退位,只需要知道 \(k\) 之后 \(A,B\) 第一个不同的位置谁大。用 \(set\) 维护所有不同的位置,上述过程可用 \(lower\_bound\) 查找。每次最多修改 \(\log|a|\) 个位置,还得在 \(set\) 中操作,复杂度为 \(O(n\log n\log|a|)\)。使用二进制压位优化,可去掉一个 \(\log\)

10.18

P3290 [SCOI2016]围棋

设当前处理的模板为 \(T\)。每一行有 \(3^m\) 种填法,对每种填法用 \(kmp\) 处理其与 \(T\) 的第一/二行的匹配关系,复杂度 \(q3^mm\)

然后设 \(f_{i,j}\) 表示处理了前 \(i\) 行,第 \(i\) 行与 \(T\) 第一行匹配的位置集合为 \(j\) 时的合法方案数。考虑转移:\(3^m\) 次枚举当前行的填法 \(T'\),设 \(T'\)\(T\) 第一/二行的匹配关系为 \(A,B\),有 \(f_{i,A}\mathrel{+}= \sum_{j\and B=\emptyset}f_{i-1,j}\)。只要用 \(fwt\)\(f_{i-1,*}\) 进行预处理就可以 \(O(1)\) 转移了,复杂度 \(n3^mq+n2^mq\)

总复杂度为 \(O(q3^m(n+m))\)

P3336 [ZJOI2013]话旧

如果题目条件为“最小值是\(0\)”,那么可以转换成从 \((0,0)\) 走到 \((n,m)\) 且不穿过 \(y=x-b\) 的方案数。这是 \(catlan\) 数的经典模型之一。推导过程:总方案数为 \({n+m\choose n}\),不符合条件的路径和从 \((0,0)\)\((m+b,n-b)\) 的路径一一对应,方案数为 \({n+m\choose n-b}\),所以答案是 \({n+m\choose n}-{n+m\choose n-b}\)

本题的条件是"极小值为\(0\)",意思就是所有 \(f(x-1)>f(x)<f(x+1)\)\(f(x)=0\),那么如果向下走就必须走到底了。设 \(f_{i,0/1}\) 表示走到 \(a_i\),从 \(a_i-1\rightarrow a_i\) 的直线向上/下的方案数。

如图,先把 \(a_{i-1},a_i\) 向右下、左下拉到 \(x\)轴,设这两点为 \((x_{i-1},0)(x_i,0)\),这两点间的路径方案数相当于把 \(k=\frac{x_i-x_{i-1}}{2}\) 个物品分成任意段,容易得到答案 \(2^{k-1}\)。这个就是 \(f_{i-1,1}\)\(f_{i,0}\) 的贡献系数。对于 \(f_{i-1,0}\),先沿黄虚线向上一段(可为 \(0\)),然后一样,方案数为 \(2^0+2^1+2^2\dots+2^{k-1}=2^k-1\),但它还可以只有一上一下,总共是 \(2^k\)。综上,\(f_{i,0}=2^{k-1}f_{i-1,1}+2^kf_{i-1,0}\)

事实上,\(f_{i,1}\)\(f_{i,0}\) 的转移是一样的,因为把最后一段折线向上翻(绿虚线),两者一一对应。

P1973 [NOI2011] NOI 嘉年华

先解决第一问:设 \(f_{i,j}\) 为在时间 \([1,i]\) 内,\(A\) 选了 \(j\) 个,\(B\) 最多的数量。枚举一个 \(k\),分类讨论 \([k,i]\) 之间的区间给 \(A\) 还是给 \(B\),从 \(f_{k-1,*}\) 转移,复杂度 \(O(n^3)\)

对于第二问,先按上述方法预处理前缀后缀的答案,然后枚举一个包含线段 \(i\) 的区间,再将前后缀的答案合并。看样子是 \(n\times n^2\times n^2\) 的,但事实上,区间总共只有 \(n^2\) 个,而合并的时候也可以利用单调性去掉一个 \(n\),复杂度变为 \(O(n^3)\)

P5527 [Ynoi2012] NOIP2016 人生巅峰

若区间长度为 \(l\),那么选出一个非空集合有 \(cnt=2^{l}-1\) 种选法。若 \(cnt>1000l\),即 \(l>13\),则至少存在 \(2\) 种权值一样的选法 \(A,B\),设 \(C=A\and B\),那么 \(A-C,B-C\) 就是一组可行的方案,所以答案定为 \(\text{YES}\)

现在只剩下长度 \(\le13\) 的区间。先预处理在 \(\%v\) 下三次幂运算的循环节,然后记录每个数被修改的次数,就可以算出这 \(10\) 个数当前的值了。然后直接暴力或者折半处理即可。

如果不处理循环节(烦),也可以用拓展欧拉定理:

\(a^b\equiv \begin{cases} a^{b\%\phi(p)}~~~~~~~~~~~gcd(a,p)=1\\ a^b~~~~~~~~~~~~~~~~~~gcd(a,p)\neq1,b<\phi(p)\\ a^{b\%\phi(p)+\phi(p)}~~~~gcd(a,p)\neq1,b\geq\phi(p) \end{cases}~~~~~~~(mod~p)\)

P4463 [集训队互测 2012] calc

为了方便 \(\text{dp}\),先指定序列递增,最后再乘上 \(n!\)。设 \(f_{i,j}\) 表示前 \(i\) 个数,最大数 \(\le j\) 的方案数,显然有转移 \(f_{i,j}=f_{i,j-1}+f_{i-1,j-1}\times j\)。接下来就非常不错了。

结论:对于 \(k\) 次函数 \(f(x)\)\(f(x)-f(x-1)\)\(k-1\) 次函数。

\(f_{i,j}\)\(j\)\(g(i)\) 次函数。移项得到 \(f_{i,j}-f_{i,j-1}=f_{i-1,j-1}\times j\)。那么 \(f_{i-1,j-1}\times j\)\(j\)\(g(i)-1\) 次函数,得到 \(g(i)-1=g(i-1)+1\),所以 \(g(n)=2n\)。于是先算出前 \(2n\) 个值,然后就可以用拉格朗日插值得出多项式,快速计算答案了。

拉格朗日插值公式:\(F(x)=\sum\limits_{i=1}^{n}\frac{\prod\limits_{j\not = i}(x-x_j)}{\prod\limits_{j\not = i}(x_i-x_j)}*y_i\)。注意只能选定义域内的点。

BZOJ4589 Hard Nim

\(p_i\) 表示 \(i\) 是否为素数。\(f_i=\sum\limits_{j\oplus k=i}p_j\times p_k\),表示只有两堆石子时异或值为 \(i\) 的方案数,那么 \(n\) 堆石子只要卷上 \(n\) 次(用快速幂、异或 \(fwt\) 优化),然后 \(f_0\) 就是答案。

异或 \(fwt\)\(FWT(A)=merge(FWT(A_0)+FWT(A_1),FWT(A_0)-FWT(A_1))\)

P6815 [PA2009]Cakes

先给每条边定向,由度数较小点指向度数大的点,于是此图成了 \(\text{DAG}\)。然后在图上枚举三元环:枚举 \(i\),枚举 \(i\rightarrow j\) 打上标记,再枚举 \(j\rightarrow k\),若 \(k\) 被打上标记则构成了三元环。

复杂度多少呢?记 \(d_i\)\(i\) 的度数。若 \(d_i\le \sqrt{m}\)\(i\) 的出边数显然 \(\le \sqrt{m}\);若 \(d_i>\sqrt{m}\),根据连边的方式,\(i\) 出边依旧 \(<\sqrt{m}\)。而枚举出边的总次数为 \(m\),所以总复杂度为 \(m\sqrt{m}\)

10.19

BAOJ3569 DZY Loves Chinese II

断开一些边后,若图不连通,则必定可以找到一个断边子集 \(S\)\(S\) 中有一条树边,和所有覆盖这条这条边的非树边。现在问题就是如何判断是否存在这样的子集。

随便搞一棵生成树,给每条非树边随机一个权值,树边的权值为覆盖它的非树边的权值异或和。若存在上述 \(S\),只需找出一些异或和为 \(0\) 的边,可用线性基判断。

P5327 [ZJOI2019]语言

暴力做法:对每个点 \(x\),求包含 \(x\) 的链的并集大小。求并集可使用线段树区间覆盖完成。

转化一下,把链 \((x,y)\) 拆成 \((1,x),(1,y)\),并减去多出来的 \((1,fa[lca(x,y)])\)。前面的部分就是求若干 \((1,x_i)\) 的并:把所有点按 \(\text{dfs}\) 序排序,答案是所有点的深度和减去相邻两点 \(\text{LCA}\) 的深度和,在线段树上对应单点修改。对于后面要减去的部分,因为这些链相交,所以只要减去所有点 \(\text{LCA}\)(即 \(\text{dfs}\) 序最小和最大的点的 \(\text{LCA}\))的深度。

在处理 \(x\) 的时候,直接继承 \(y\in son(x)\) 的信息(线段树合并),并加入在 \(x\) 点的变化。复杂度 \(O(n\log n)-O(n\log^2n)\)

BZOJ2741【FOTILE模拟赛】L

首先定义 \(b_i\)\(a\) 的异或前缀和,询问就被转化成求 \(b_x\oplus b_y\ \ x,y\in[l-1,r]\) 的最大值。

\(\sqrt{n}\) 个元素分为一块。使用可持久化 \(\text{trie}\) 树和暴力可在 \(n\sqrt{n}\log n\) 时间内算出所有 \(s_{i,j}\) 表示块 \([i,j]\) 内的答案。

对于每次询问,中间整段块的答案已经有了,只剩下两边 \(\sqrt{n}\) 个数和其他数异或的答案没算,还是 \(n\sqrt{n}\log n\) 暴力即可。

BZOJ4184 shallot

只有加入、区间查询,强制在线:对每一个前缀维护线性基,原本线性基的每一位取的是最靠左的数,现在改成最靠右的数,就可以处理询问了。

然而本题又要加,又要删。把所有操作离线,弄到时间轴上,相当于在时间 \([l,r]\) 加入 \(x\),并询问某个时间的答案。正符合线段树分治的形式,复杂度 \(O(n\log n\log V)\)

P3350 [ZJOI2016]旅行者

网格图分治。每次取长边两中点连线 \(L\) 切开,计算 \(L\) 上点到其他点的最短路,用经过 \(L\) 的路径更新询问答案(只更新两点都在当前矩形内的),并递归下去。每次选的短边长度 \(L\le\sqrt{nm}\),所以复杂度有保证。

10.20

P3247 [HNOI2016]最小公倍数

每次询问只能加入 \(a_i\le A,b_i\le B\) 的边。把边和询问按 \(a\) 排序,双指针加入 \(a_i\le A\) 的边,第一个条件就解决了。

然后对第二个条件分块处理:维护 \(cnt\) 个并查集,第 \(i\) 个记录加入 \(b_i\) 最小的 \(\frac{m}{cnt}\times i\) 条边后的连通性。每次询问的时候先找到 \(B\) 所在块的前一个并查集,那么至多只有 \(\frac{m}{cnt}\) 条边没被加入,暴力加入并撤销。复杂度 \(O(cnt\times m\log n+q\frac{m}{cnt}\log n\ge m\sqrt{q}\log n)\)

虽然本题的并查集需要撤销,但只有加入零散的 \(\frac{m}{cnt}\) 条需要撤销,其它修改还是可以路径压缩的,所以 \(\log n\) 好像可以变成 \(\alpha(n)\)

P3250 [HNOI2016]网络

整体二分:对所有询问一起二分、判定。

二分答案为 \(mid\),修改 \(\ge mid\) 的边并对每个询问判定。撤回修改。然后把答案 \(\ge mid\) 的询问扔到右边,\(<mid\) 的扔到左边,边也一样,再递归下去。

对询问一起判定的过程:加入链,清除链,看看当前有无不经过 \(x\) 的链。实际上只要知道 \(x\) 被多少条链覆盖了,树上差分转化成单点修改和区间查询,用树状数组维护。

DAG 计数

对一张 \(\text{DAG}\) 枚举零度点集合 \(S\),设剩下点的集合为 \(T\),它们之间的连边方向只能 \(S\rightarrow T\)。但 \(T\) 中可能存在其它零度点,所以要乘上容斥系数 \((-1)^{|S|+1}\)。 递推的时候枚举 \(|S|\),得到 \(f(n)=\sum_{i=1}^n (-1)^{i+1} {n\choose i}f(n-i)2^{i(n-i)}\)

P3175 [HAOI2015]按位或

\(\text{min-max}\) 容斥:\(\max (S)=\sum\limits_{\varnothing\ne T\subseteq S}(-1)^{|T|-1}\min (T)\)。推导过程:给 \(S\) 排序,设容斥系数为 \(f(i)\),写出 \(S\) 中每个数的贡献,转换到函数 \(g(n)=[n==0]\),然后二项式反演算出 \(f(i)\)。可以拓展到第 \(k\) 大: \(kthmax(S)=\sum\limits_{\varnothing\not=T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\min(T)\)

回到本题,套用 \(max(S)=\sum\limits_{T\subseteq S}(-1)^{|T|+1}min(T)\)。其中,\(S\) 里包含每个 \(1\) 出现的期望时间。问题就变成了求 \(min(T)\)。有 \(min(T)=\frac1{\sum_{i\and T\not=\varnothing}p_i}=\frac1{1-\sum_{i\and T=\varnothing}p_i}\)\(fwt\) 处理分母就好了。

P3331 [ZJOI2011]礼物

先把三维转二维,剖出第 \(k\) 层,计算以 \((i,j)\) 为右下角的最大正方形边长 \(f_{i,j,k}\)\(f_{i,j,k}\le min(f_{i-1,j,k},f_{i,j-1,k})+1\),从上界开始向下枚举,直到可行。这样暴力每个点均摊 \(O(1)\),总复杂度 \(O(n^3)\)

然后再 \(dp\) 拓展回三维:对每个 \((i,j)\) 若选了 \([l,r]\) 层,答案为 \((r-l+1)\times\min_{k=l}^{r} f_{i,j,k}\),于是可以枚举每个 \(p\) 作为最小值,用单调栈求出 \(f_{i,j,p}\) 为最小值的 \(l,r\) 的边界,更新答案,这部分也是 \(O(n^3)\)

P6665 [清华集训2016] Alice 和 Bob 又在玩游戏

定义 \(SG(x)\)\(subtree(x)\) 内游戏的 \(SG\) 值。最后答案为每棵有根树 \(SG(root)\) 的异或和。问题变成对每棵树求解 \(\rightarrow\) 对于 \(x\),得到了所有 \(SG(y)\ \ y\ne x,y\in subtree(x)\),如何求 \(SG(x)\)

按照定义,需要计算每个后继状态的值,也就是枚举删除链 \((x,y)\),对删完后分成的若干棵树的 \(SG(root)\) 求异或和,再对这些值求 \(mex\)

考虑优化这个过程。\(y=x\) 容易计算。假设 \(y\in subtree(z),z\in son(x)\),删除之后 \(subtree(z)\) 内的值为 \(Z\)\(V=xor_{p\in son(x)} SG(p)\),最终答案就是 \(Z\oplus V\oplus SG(z)\)。当 \(z\rightarrow x\) 后 ,\(Z\oplus V\oplus SG(z)\) 取值集合中的所有数异或了 \(V\oplus SG(y)\),并且要合并所有 \(z\in son(x)\) 的信息,可用 \(\text{trie}\) 合并、全局异或解决;至于询问 \(mex\),直接在 \(\text{trie}\) 树上二分。

10.21

P4224 [清华集训2017]简单数据结构

注意到本题的特殊限制有“元素两两不同“”每个数最多插入 \(10\) 次“,它们为暴力做法提供了复杂度保障。

”元素两两不同“暗示答案长度至多为 \(\log V\),对每个位置维护 \(f_i\) 表示以 \(i\) 为开头的最长序列,\(g_{i,j}\) 表示以 \(i\) 为开头的长度为 \(j\) 的序列可以从多少个地方转移。同时记录 \(ans_i\) 表示长度为 \(i\) 的序列的不同开头数。

在开头加入 \(x\),只需枚举 \(x\) 的倍数向 \(x\) 转移,每个数最多插入 \(10\) 次,上界是 \(10q\log V\)。在开头删除 \(x\),直接在 \(ans\) 里修改然后删除。

在末尾加入/删除 \(x\),先枚举 \(x\) 的因子进行修改(称这个过程为 \(upd\)),然后从大到小枚举 \(x\) 的因子 \(y\),如果 \(f_y\) 发生变化,执行 \(upd(y)\)。看着挺暴力,但由于条件限制,复杂度还是对的。

P4247 [清华集训2012]序列操作

\(k\) 很小,在线段树的每个节点上都记录 \(k\) 个值,分别表示在区间内选 \(1,2,\dots k\) 个数的答案。合并两个节点的时候 \(k^2\) 暴力卷积即可。

对于取反操作,相当于让选奇数个数的答案取反,选偶数个的不变。

对于区间加 \(v\)\(x_1x_2\dots x_n\rightarrow (x_1+v)(x_2+v)\dots(x_n+v)\),展开可得 \(v^j\)\(f_i\) 的贡献系数为 \(f_{i-j}\times {L-(i-j)\choose j}\)

于是所有操作都可以在线段树上处理了,复杂度 \(O(k^2n\log n)\)

P3706 [SDOI2017]硬币游戏

\(S\) 为还没结束的状态(概率),\(T_i\) 为第 \(i\) 个人获胜的状态。

要在 \(S,T\) 之间建立关系。能不能直接在 \(S\) 后面加上 \(s_i\) 然后就和 \(T_i\) 扯上呢?显然不行,因为可能还没得到 \(s_i\) 先得到了 \(s_j\)。此时有 \(s_i[1,k]=s_j[m-k+1,m]\),即 \(S+s_i[1,m]=T_j+s_i[k+1,m]\)

于是可对每个 \(s_i\) 列出关系式 \(\frac1{2^m}S=\sum_{j=1}^n\sum_{k=1}^m[s_i[1,k]=s_j[m-k+1,m]]\frac1{2^{m-k}}T_j\),还有 \(\sum T_i=1\)\(n+1\) 个式子 \(n+1\) 个未知数,高斯消元 \(n^3\) 求解。

P2371 [国家集训队]墨墨的等式

\(V=\min a_i\),若能表示出 \(kV+r\),必能弄出 \((k+1)V+r\),所以只要知道对于每种 \(r\),最小的 \(k\) 是多少。

\(\%V\) 的余数间连边:对每个 \(a_i\) 枚举 \(r\)\(r\to(r+a_i)\%V\),权值为 \(\lfloor\frac{r+a_i}{V}\rfloor\)。然后从 \(0\) 开始求单源最短路即可。

这里选最小的 \(a_i\) 与正确性无关,只是为了快一点,省一点。

P4466 [国家集训队]和与积

\(d=\gcd(a,b),a_0=\frac{a}{d},b_0=\frac{b}{d}\),原条件变为 \((a_0+b_0)d|a_0b_0d^2\rightarrow (a_0+b_0)|d\)

不难发现,\(a_0+b_0\leq d\leq \frac{n}{b_0}\),所以 \(a_0,b_0\leq\sqrt{n}\),可以快乐地枚举 \(a_0,b_0\)

\(\sum_{a_0=1}^{\sqrt n}\sum_{b_0=a_0+1}^{\sqrt n}\lfloor\frac{\lfloor\frac{n}{b_0}\rfloor}{a_0+b_0}\rfloor[gcd(a_0,b_0)=1]\)

带入莫比乌斯反演,并更改枚举项、变换枚举顺序,得到:

\(\sum_{d=1}^{\sqrt n}\mu(d)\sum_{b_0=2}^{\lfloor\frac{\sqrt n}d\rfloor}\sum_{t=b_0+1}^{2b_0-1}\lfloor\frac{\lfloor\frac n{b_0d^2}\rfloor}{t}\rfloor\)

枚举 \(d,b_0\)\(t\) 可以数论分块,复杂度大概是 \(O(n^{0.75}\log \sqrt{n})\)

P4586 [FJOI2015]最小覆盖双圆问题

先看看单圆覆盖。设当前点集的最小圆覆盖为 \(C\),若新加入一个点 \(P_i\) 不在 \(C\) 中,则 \(P_i\) 一定在新的最小覆盖圆上,固定 \(P_i\) 并暴力重构:初始化圆心为 \(P_i\),半径为 \(0\);然后枚举第二个点 \(P_j\)(不在当前圆内),此时有两个点,令圆心为 \(P_iP_j\) 中点,\(r=\frac{dist(P_i,P_j)}{2}\); 最后枚举第三个点 \(P_k\)(不在当前圆内),此时三点定圆。

说的不是很清楚,放一个伪代码:

for (i = 1 to n) if (P[i] 不在 C 内) {
	C = {P[i], 0};
	for ( j = 1 to i - 1) if (P[j] 不在 C 内) {
		C = {0.5 * (P[i] + P[j]), 0.5 * dist (P[i], P[j])};
		for (k = 1 to j - 1) 
			if(P[k] 不在 C 内) C = 外接圆 (P[i], P[j], P[k]);
	}
}

复杂度多少?把点随机打乱后,\(P_i,P_j\) 不在 \(C\) 内概率为 \(\frac{3}{i},\frac{3}{j}\),期望复杂度 \(O(\sum_{i=1}^n(\frac3i\times (\sum_{j=1}^i\frac3j\times j))=9n)\)

本题要求双圆覆盖,显然能够找到一条线 \(L\)\(L\) 的左侧用第一个圆,\(L\) 的右侧用第二个圆覆盖最优。先枚举 \(L\) 的倾斜角,每次转过 \(\frac{\pi}{100}\),然后还要确定截距。暴力显然是不行的。发现随着截距改变,左侧最小覆盖圆半径 \(R_1\) 递增,右侧 \(R_2\) 递减,而要求的是 \(min\{\max(R_1,R_2)\}\),如果画成函数图像,一定在交点处最优,所以二分交点求解。复杂度 \(O(200n\log n)\)

P2172 [国家集训队]部落战争

最小路径覆盖:把每个点拆成入点和出点,按照题意连边。每选一条边,相当于合并两条路径,数量 \(-1\),所以答案是总点数 \(-\) 二分图最大匹配。

P3653 小清新数学题

筛出 \([1,10^6]\) 内的素数,统计这部分素数的贡献。对于剩下的数 \(x\),最多由两个 \((10^6,10^{18}]\) 的素因子相乘,分类:1、用 \(MillerRabin\) 检测后是素数;2、是平方数;3、剩下的都是两个素因子相乘。统计一下就好了。

\(\text{MillerRabin}\) 素数检测:针对较大值域的单个数进行素数判定。费马小定理 \(a^{p-1}\equiv1\pmod p\),反过来不一定成立,称 \(a^{p-1}\equiv1\pmod p\) 但不是素数的 \(p\) 为伪素数。发现对于每个 \(a>1\),伪素数个数小于素数的 \(\frac{1}{4}\),可以多测几个 \(a\) 来判断 \(x\) 是否为素数,正确概率极大。这种做法比较简单,要注意对 \(a=x\) 特判。

可以使用二次探测定理提高测试效率。二次探测定理:若 \(p\) 为奇素数,\(x^2\equiv 1\pmod p\) 当且仅当 \(x=1,p-1\)

选取一个质数 \(p\)\(x\) 测试:\(x=p\)\(x\) 为质数;\(x=kp(k>1)\),合数;\(p^{x-1}\%x\ne1\),合数;这些都是常规操作,接下来使用二次探测。令 \(k=x-1\),只要 \(k\) 为偶数就重复操作:将 \(k\) 除以 \(2\),记 \(t=p^k\% x\),若 \(t\ne1,p-1\)\(x\) 非素数;若 \(t=p-1\),无法继续套用二次探测定理,结束。选取大约 \(10\)\(p\) 进行上述过程。

使用 \(\text{MillerRabin}\) 素数检测 写完后最好测验一下其准确性,避免奇葩错误。

P4688 [Ynoi2016] 掉进兔子洞

对于三个区间分别用 \(bitset\) 表示其中数值出现的情况(用莫队处理),然后数 \(A\&B\&C\) 里的 \(1\) 的个数就可以得出答案。因为有重复出现的数字,离散化的时候不要 \(unique\),让每个数第一次出现为 \(x\),再出现为 \(x+1,x+2\dots\)

如果直接一遍莫队并存储信息,空间消耗为 \(\frac{nm}{w}\),不太够,可以把询问分成若干组处理。

P5355 [Ynoi2017] 由乃的玉米田

使用莫队处理。

对于加减法,用 \(bitset\) 维护每个数的存在性,然后左移、右移、按位与就可以判断了。(判断加法需同时维护 \(v,max-v\) 的存在性 )

对于乘法,暴力枚举 \(v\) 的因数分解即可。

对于除法,若 \(v\ge\sqrt{mx}\),只有 \(\sqrt{mx}\) 种可能,同样可以暴力;若 \(v<\sqrt{mx}\),不用莫队了,把每种 \(v\) 的询问拿出来处理一遍(记录每个位置的上一个与其匹配的位置\(\dots\))。

P4689 [Ynoi2016] 这是我自己的发明

不管如何换根,一棵子树的 \(\text{dfs}\) 序区间可表示为原树上的两段区间。于是询问就被转化成:从 \(\text{dfs}\) 序的两段区间中选出两个相同的数,记作 \(f(l1,r1,l2,r2)\)。每个询问有四个变量,不好搞。把它差分成前缀的形式,只需要计算若干 \(f(1,r1,1,r2)\),用莫队处理。

P5304 [GXOI/GZOI2019]旅行者

如果把这 \(k\) 个点分成 \(A,B\) 两组,以 \(A\) 为起点跑一遍多源最短路,就求出了 \(A\rightarrow B\) 的最小答案。那么如果进行若干次划分,对于 \(\forall x,y\),都在某一次被划到了不同的两组,最终答案就求出来了。枚举二进制位,按照这一位为 \(0/1\) 分成两组计算,这样的划分显然是符合要求的,并且只有 \(\log n\) 次。

LOJ#6485. LJJ 学二项式定理

单位根反演:\([k|n]=\frac{1}{k}\sum_{i=0}^{k-1}\omega_k^{ni}\)。证明:\(k|n\) 时右边是 \(\frac{1}{k}\times k\)\(k\not|n\),用等比数列公式得到右边为 \(0\)

枚举 \(\%4\) 余数 \(k\),得到: \(\sum\limits_{k=0}^3a_k\sum\limits_{i=0}^nC_n^i\cdot s^i\cdot[4|(i-k)]\)

把后面的用反演带入:\(\frac14\sum\limits_{k=0}^3a_k\sum\limits_{i=0}^nC_n^i\cdot s^i\cdot\sum_{j=0}^3\omega_4^{j(i-k)}\)

改变枚举顺序,并把 \(w_4\) 的质数拆开,得到:\(\frac14\sum\limits_{k=0}^3a_k\sum\limits_{j=0}^3\omega_4^{-jk}\sum\limits_{i=0}^nC_n^i\cdot s^i\times \omega_4^{ij}\)

后面那个可用二项式定理化简,得到:\(\frac14\sum\limits_{k=0}^3a_k\sum\limits_{j=0}^3\omega_4^{-jk}(s\cdot\omega_4^j+1)^n\)。可以用快速幂求了。

取模意义下的单位根:\(w_k=pow(g,\frac{mod-1}{k})\),其中 \(g\) 为原根。

10.22

P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III

\(\sqrt{n}\) 分为一块,先预处理 \(f_{i,j}\) 表示块 \([i,j]\) 内的答案,复杂度 \(O(n\sqrt{n})\)。对于询问,中间整块的答案 \(ans=f_{x,y}\) 已经有了,还要考虑两边零散的 \(\sqrt{n}\) 个数。

对于每种数开个 \(vector\) 记录其出现位置,然后对 \(\sqrt{n}\) 种数判断区间里是否有 \(ans+1\) 个,如果有就 \(ans\mathrel{+}=1\),并继续判断。因为 \(ans\) 至多增加 \(\sqrt{n}\),所以单次复杂度 \(O(\sqrt{n})\)

P5305 [GXOI/GZOI2019]旧词

如果把指数 \(k\) 去掉,就是P4211\(path(root,x),path(root,y)\) 的重合部分是 \(path(root,lca(x,y))\)。树链剖分,先对 \(path(root,x)\) 路径 \(+1\),再询问 \(path(root,y)\) 的和就是 \(depth(lca(x,y))\)。利用这一思想就可以解决 \(\text{P4211}\)

本题加上了指数 \(k\),只要修改每个点的贡献:原本每个点的权值为 \(1\),现在把深度为 \(d\) 的点的权值差分,赋为 \(d^k-d^{k-1}\),就可以一样做了。

10.24

P4364 [九省联考2018]IIIDX

题意就是给出一棵树(结构有特殊性质),\(\forall x,val_x\ge val_{fa_x}\),而 \(val\)\(d\) 的排列,求 \(val\) 的最大字典序。

直接贪心,依次考虑编号从小到大的点 \(x\),设其子树大小为 \(sz_x\),那么选 \(val_x\) 的时候显然要留出 \(sz_x-1\) 的空位,还要给同一层的 \(y<x\) 的子树也留出 \(sz_y-1\) 的空位。用线段树维护当前每个数的排名(把预留的去掉),求 \(val_x\) 就是在线段树上二分,若有相同值 \(val_x\) 要选最右边的。

然而这题还是有些奇怪的(成为黑题的原因吧),说不太清楚。差不多是这么个意思。

P3160 [CQOI2012]局部极小值

局部极小值的四周没有局部极小值,那么最多 \(\lceil\frac{n}{2}\rceil\times\lceil\frac{m}{2}\rceil=8\) 个极小值,可以状压。从小到大填入每个数,\(f_{i,j}\) 表示填了数字 \([1,j]\),局部极小值填充的状态为 \(j\) 的方案数。每个极小值必须先于周围空格填入,按照这个枚举转移即可。

现在保证了是极小值的位置都是极小值,但没有保证不是极小值的位置一定不是极小值。所以爆搜得出每种可能的极小值局面,然后容斥。

P4292 [WC2010]重建计划

先用分数规划(二分答案)转化为判定性问题,然后使用点分治。计算跨过 \(x\) 的链的答案:用“滑动窗口”(单调队列)把子树合并起来,每次的复杂度为当前子树最深深度加上之前子树的最深深度,所以要按最深深度排序,从小到大处理。

知耻而后勇。最后的机会了,NOIP冲冲冲!!!

10.25

BZOJ4762 最小集合

\(f(S)=\bigwedge_{a\in S} a,\ S/a\) 表示从集合 \(S\) 里拿掉元素 \(a\)。按照题意写出答案为 \(\sum\limits_S [f(S)=0]\and [\forall{a\in S},f(S/a)\not =0]\)。比较麻烦的是 \(\forall\) 的条件不好记录。

把后面的部分容斥,得到 \(\sum\limits_S [f(S)=0]\and \sum_\limits{S'\subseteq S}[\forall {a\in S'},f(S/a)=0](-1)^{|S'|}\)

\(\ne 0\) 变成了 \(=0\),于是条件可以写成 \([(\bigvee\limits_{a\in S'} f(S/a))=0]\),这个东西就可以放在 \(\text{dp}\) 状态里了。

\(f_{i,j,k}\) 表示处理了 \(i\) 个数,\(j=f(S)\)\(k=\bigvee\limits_{a\in S'} f(S/a)\)\((-1)^{|S'|}\) 的和。分类转移就好了。

复杂度为 \(O(n\times 3^{10})\)

10.26

P7520 [省选联考 2021 A 卷] 支配

1、若 \(x\) 支配 \(y\)\(y\) 支配 \(z\),则 \(x\) 支配 \(z\)

2、若 \(x,y\) 都支配 \(z\),则 \(x,y\) 之间也存在支配关系

3、对于 \(x\),设 \(D_x\) 为其支配集。根据第\(2\)条,\(D_x\) 中有且仅有一个 \(y\) 满足 \(D_x\) 中除了 \(x\) 都支配 \(y\),连边 \((fa_x=y,x)\),最终会构成支配树。

4、这个 \(y\) 就是支配集最大的那个点,于是可以暴力构建。

5、加入一条边,\(D_x\) 变化,要么 \(D_{fa_x}\) 变化,\(fa_x\) 不再支配 \(x\)

6、加入边 \((u,v)\),若 \(fa_x\) 不再支配 \(x\),则删除 \(fa_x\) 后,\(1\) 可达 \(u\)\(v\) 可达 \(x\)

7、具体地,删除每个点后爆搜一遍,得出所有 \(D_x\),然后按照\(4\)构建支配树,复杂度 \(O(n^2)\)。预处理\(6\)所需的信息,每次询问为 \(O(n)\)。总复杂度 \(O(n(n+q))\)

P7516 [省选联考 2021 A/B 卷] 图函数

对于 \(f(u,G)\),若 \(v\)\(1\) 的贡献,则 \(u\rightarrow v,v\rightarrow u\) 都存在不经过 \(\le v\) 的点的路径。

一种做法就是用 \(\text{floyd}\) \(O(n^3)\) 算出 \(d_{u,v}\) 表示 \(u\rightarrow v\) 不经过 \(\le u\) 的最大路。“最大路”定义为经过的边中最小编号最大的路径(最多删掉几条边后还存在)。然后答案就很好算了。得分44——100。循环的时候注意上下界,可以使用指针卡常。

还有一种是先枚举 \(u\),然后把边倒着加进去(正图反图都要处理),加入 \((u,v)\),若都没被标记,先留着;若有一个被标记,就从这个点出发搜索。每个点最多经过一次,复杂度 \(O(n(n+m))\)。还可以换用 \(\text{bitset}\),复杂度 \(O(\frac{n^3}{w})\)

P7519 [省选联考 2021 A/B 卷] 滚榜

两个条件:总分单调,封榜后做题数单调。先让所有人的总分都变成最大值(预先计算费用),强行满足第一个条件。若顺序确定,之后每次操作都是让后缀 \(+1\)(保持第一个条件满足),去满足第二个条件。直接 \(\text{dp}\),令 \(f_{i,j,k}\) 表示已经处理的集合为 \(i\),最后一个人是 \(j\),还剩 \(k\) 次过题数的答案。暴力转移就好了,复杂度 \(O(2^nn^2m)\)。如果使用一些枚举技巧是跑不满的。

已经发榜的人还要和未发榜的人比较,所以初始化要注意一下。

P7515 [省选联考 2021 A 卷] 矩阵游戏

先随便构造出一组 \(a\),然后进行调整。给 \(a\) 的第 \(i\)\(+x_i,-x_i,+x_i,-x_i\dots\),第 \(j\)\(+y_j,-y_j,+y_j,-y_j\dots\),并不改变 \(b\)。可以列出若干关于 \(x,y\) 的不等式。调整一下就都变成了作差的形式,使用差分约束求解。

AT4439 [AGC028E] High Elements

依次考虑每一位,是否可以填 \(0\)。需要判断若当前位填 \(0\) 后面是否可行。

称原本序列中的前缀最大值为“旧最大值”,其余的为”新最大值“。结论:若有解,一定可以让其中一个序列只有”旧最大值“。证明:若两个序列都有”新最大值“ \(x,y\),那么交换 \(x,y\),之后 \(x,y\) 就都被”遮住了“,而两个序列的前缀最大值个数仍相等。

于是考虑判断能否构造出其中一个序列只有”旧最大值“的方案。设 \(A\) 只有”旧最大值“, 另一个序列为 \(B\)。当前 \(A,B\) 前缀最大值的数量为 \(c_a,c_b\),之后还没动的”旧最大值“数量为 \(c\)\(B\) 之后的”新/旧最大值“数量分别为 \(p,q\),则需要满足条件 \(c_a+c-q=c_b+p+q\rightarrow 2q+p=c_a+c-c_b\)

等式右边是定值。左边的 \(2q+p\),可以转换成”带权上升序列“:让”旧最大值“价值为 \(2\),”新最大值“为 \(1\),在后面是否能找出一个权值为 \(c_a+c-c_b\) 的上升序列。发现总价值由若干 \(1,2\) 组成,那么若 \(x\) 可达,\(x-2\) 必可达,所以只要分别计算总和为奇数/偶数的最大上升序列。可用线段树维护。

上述过程基于”\(A\)中只有旧最大值“的假设,而这个假设也的确成立:对于后面任意一个非”旧最大值“的位置 \(x\),若 \(x\) 被塞到 \(A\) 中成了”新最大值“,说明能遮住 \(x\) 的已经在 \(B\) 里,那么不妨把 \(x\) 扔到 \(B\) 里,并不会增加 \(B\) 的前缀最大值数量。

10.27

CF1601C Optimal Insertion

\(b\) 排序,显然若 \(i<j\)\(b_i\) 插在 \(b_j\) 左边更优。所以 \(b\) 之间没有逆序对,只要考虑 \(a,b\) 之间的逆序对。然后又发现 \(b_j\) 插入的最优决策点也一定在 \(b_i\) 右边。

一种方法是从左往右逐个插入,用线段树维护每个位置的答案。但这样比较烦,比较慢,还容易错。使用分治,每次算出 \(b_{mid}\) 的最优决策点,然后往两边递归。这样计算最优决策点的时候可以直接暴力扫,不需要数据结构维护。

CF1601D Difficult Mountain

结论:将所有人按 \(\max(s,a)\) 排序,依次考虑,能爬就爬,这样的方案最优。

证明比较麻烦。分类讨论?可能可以考虑交换两个人后的变化来证明。

P3270 [JLOI2016]成绩比较

总方案数可以拆成人员分配和成绩分配两部分。

人员分配(被碾压的是哪些人?第 \(i\) 门课被超过的是哪些人?):对第一个问题容斥,第二个直接算。设 \(f(x)\) 表示定了 \(x\) 个人被碾压,每门课被 \(1\) 超过的人员分配方案数,不难得到:\(f(x)={n-1\choose x}\times\prod\limits_{i=1}^m {n-1-x\choose R_i-1}\),容斥一下就是人员分配方案数 \(num=\sum\limits_{i=k}^{n-1}(-1)^{i-k}\times {i\choose k}\times f_i\)。这里有一个 \(i\choose k\) 别忘了,因为每种“至少碾压 \(i\) 个人”对应 \(i\choose k\) 个“至少碾压 \(k\) 个人”。

还要考虑成绩的分配。这个很好写,枚举第一个学生第 \(i\) 门课的成绩 \(j\) 得到 \(g(i)=\sum\limits_{j=1}^{U_i} j^{n-R_i}\times (U_i-j)^{R_i-1}\)。但 \(U_i\) 的范围为 \(10^9\),需要优化。\(j^{n-R_i}\times (U_i-j)^{R_i-1}\) 是关于 \(j\)\(n-1\) 次项,套上 \(\sum\) 后成了关于 \(U_i\)\(n\) 次多项式。算出前 \(n+1\) 个值后使用拉格朗日插值算出 \(g(i)\)

最终答案只需将二者相乘,即 \(num\times \prod g(i)\)

10.28

CF1601E Phys Ed Online

\(l_i\%k\) 相同的询问放在一起处理,问题就成了:给定 \(l,r\),求 \(\sum\limits_{i=l}^{r} (\min a[l,i])\)

\(f_i=\sum\limits_{j=i}^{n}(\min a[i,j])\)\(nxt_i=\min\limits_{j>i,a_j<a_i}\{j\}\),有递推式 \(f_i=f_{nxt_i}+a_i\times(nxt_i-i)\)

对于询问 \(l,r\),令 \(p\)\([l,r]\)\(a\) 最小的位置,有 \(ans=f_l-f_p+a_p\times(r-p+1)\)

复杂度 \(O(n\log n)\)

P6669 [清华集训2016] 组合数问题

\(\text{Lucas}\) 定理:\({n\choose m} \equiv {m/p\choose n/p}\times{m\%p\choose n\%p}\pmod p\)。观察发现,若把 \(i,j\) 都写成 \(k\) 进制数,当且仅当出现某一位 \(i<j\)\({i\choose j}\equiv 0\pmod p\rightarrow p|{i\choose j}\)

数位 \(\text{dp}\),在状态里记录 \(i,j\) 的相对关系、\(i\)\(n\)\(j\)\(m\) 的大小关系,暴力转移。

P5933 [清华集训2012]串珠子

\(f_s\) 表示使集合 \(s\) 连通的方案数,直接转移容易出现重复。考虑计算反面:使 \(s\) 不连通的方案数 \(g_s\).然后用总方案去减。计算 \(g_s\) 时选一个点为特殊点,枚举与特殊点连通的集合 \(t\),有 \(g_s=\sum f_t\times g_{s\oplus t}\)。复杂度 \(O(3^n)\)。使用子集卷积和多项式科技可优化至 \(O(n^22^n)\)

10.30

CF1598G The Sum of Good Numbers

以下结论均基于“\(a,b,x\) 中不出现 \(0\)” 的条件。

\(a\ge b\),必有 \(|a|=|x|\)\(|a|=|x|-1\)

1、\(|a|=|x|-1\),必有 \(|b|=|x|-1\),只有 \(n\) 种。

2、\(|a|=|x|\),此时需先求出二者的 \(\text{lcp}\),然后和情况 \(1\) 类似,也只有 \(n\) 种。

总共可能的结果只有 \(2n\) 种,然后拿哈希 \(\text{check}\) 一下是否可行。

10.31

CF1569F Palindromic Hamiltonian Path

看着高级,实际上是个暴力题。只需要知道哪些点同色时合法,乘上组合数就是答案。也就是求颜色的划分,总状态数为贝尔数,约为 \(10^5\)

初始状态是两两配对的情况,可以直接暴力搜索,复杂度 \(12\times 11\times10\times 9\times 8\times 7\)。然后枚举哪两个并在一起转移。

11.01

CF1555F Good Graph

每条边最多属于一个环,否则这两个环拼在一起异或值为 \(0\)。动态加边的构成先离线建出生成树。然后对于每次询问,判断这条链上的边是否都没被覆盖、异或值是否为 \(0\)。第二个条件容易判断,第一个条件直接在 \(\text{dfs}\) 序上用树状数组暴力修改(差分,前缀和),反正每条边只被覆盖一次。

CF1535F String Distance

先把所有字符串排序,然后算出相邻两个字符串的 \(lcp\) 长度 \(L_i\)。字符串 \(i,j\)\(lcp\) 就是 \(L\) 在区间 \([i,j]\) 内的最小值。这部分复杂度为一个 \(\log\)

发现答案只能是 \(1,2,1337\) 三种,\(1337\) 的容易解决。只要算出答案为 \(1\) 的答案就出来了。若 \(f(x,y)=1\) ,除去一段后缀一段前缀,中间部分 \(x\) 有序。

方案一:预处理后直接暴力可以弄到 \(n^2\)。考虑另一种做法,先枚举 \(x\),然后枚举两个切割点,左边一段右边一段哈希后统计一下,答案就可以算了,设 \(S=|s_i|\times n\le 2\times 10^5\)。复杂度 \(n\times (\frac{S}{n})^2=\frac{S^2}{n}\)(直接 \(map\) 会再带一个 \(\log\))。根据 \(n\) 的数值选取不同的做法,复杂度为 \(\min(n^2,\frac{S^2}{n})\le S^{\frac{4}{3}}\)

方案二:枚举 \(x\),根据 \(lcp(y,x)\) 的单调性用单调栈维护 \(lcp(y,x)\) 相同(\(=s\))的 \(O(m)\) 段区间。对每段区间分别搞:算出从 \(s+1\) 开始的 \(s_x\) 的极长有序区间 \([s+1,t]\),要统计 \([t+1,|s_x|]\) 这一段与 \(x\) 相同的 \(y\) 的数量。把所有串反插入 \(\text{trie}\) 树,然后二分。

P5955 [POI2018] Pionek

只有在答案向量上投影为正的向量会产生贡献。将向量极角排序后,枚举答案向量极角 \(x\),贡献为正的区间随 \(x\) 变化单调,双指针处理。

10.02

Codechef Maximum GCD

暴力做法:分类讨论,看看有没有选 \(a_1\),如果选了 \(a_1\),只需枚举另一个;否则枚举 \(a_1\) 的约数看看能否成为答案。可以拿到 \(60\) 分。

一个乱搞:先把 \(a\) 排序去重,每种数至多留 \(3\) 个,然后讨论有没有选前 \(60\) 个,如果选了做法不变;如果没选,这时候只要枚举 \(a[1,60]\)\(\gcd\) 的约数。很可惜,最后一个 \(\text{subtask}\) 有一个点无法通过。不选前 \(60\) 个了,随机选 \(60\) 个,还是过不了。猜测这个点大概形如 \(k,2k,3k,4k\dots,nk,k\le1e13\),可以先把所有数的 \(\gcd\) 除掉再处理,不知道能不能过。反正如果不是 \(\text{ACM}\),这个乱搞应该可以拿不少分。

正确做法:选择的这个 \(i\ (i<j)\) 满足 \(s_i\ne s_{i-1}\),其中 \(s_i\) 为前缀异或和。这样的 \(i\) 不超过 \(\log 10^{18}\) 个,对每个暴力就好了。如果要更快一些,有用的 \(j\) 也只有 \(\log 10^{18}\) 个...

证明:反证,若 \(s_i=s_{i-1}\),还要用 \(i\),答案 \(x|s_i\)\(s_i|a_i,s_i|a_{i-1}\),那么用 \(i-1\) 的效果是一样的。

posted @ 2021-09-25 10:05  -敲键盘的猫-  阅读(33)  评论(0编辑  收藏  举报