2023.2 做题记录
写在前面
经历过许多模拟赛原题(或见过套路)忘掉不会做的惨痛教训后,在教练启发下决定效仿一些大佬以做题记录的形式记录做过的需要重视的题。
本文以及之后的所有做题记录仅供个人总结复习用,不作为题解参考。
2.6
[PA2014]Druzyny
标签:计数DP,CDQ分治,线段树
来源:与前几天模拟考出现过的题类似的题
可以快速想出来朴素的 \(n^2\) DP,先求最大值,记录方案再开一个辅助数组即可。
考虑题解的限制条件比较复杂,转移不连续,而且任意两点都有可能进行转移,用 cdq 分治解决。
设当前已经处理好了 \(f_{l}\) 到 \(f_{mid}\) ,将要更新 \(f_{mid+1}\) 到 \(f_{r}\),考虑从 \(mid\) 到 \(l\) 枚举左边,对每个左边的点都有一个限制条件 \(up,down\),其中 \(down\) 是 \(c_l\) 到 \(c_{mid}\) 的最大值,表示至少取的数目,\(up\) 类似,那么能转移的就是一段区间,可以离线扫描线进行差分。
对于右边从 \(mid+1\) 枚举到 \(r\),那么有和左边类似的限制,之前我们已经离线过了左边的点,在线段树上更新,右边的点根据限制线段树上区间查询获得最大值,方案数可以一并更新。
总时间复杂度为 \(O(nlog^2n)\),不过时间限制给的很宽裕。
一开始认为模拟考的题也可以cdq,魔改了好久始终不对。
经过与Larunatrecy的讨论后得出了两道题的本质区别:
本题的上界是取min,所以跨过mid的限制条件必须两边同时满足,这也就证明了扫描线过程的正确性,而模拟考的题上界是取max,可以满足一边而另一边不满足,很容易举出例子,所以模拟考的题是利用单调栈的套路而非cdq,本题也不能用单调栈而只能用cdq。
提交记录。
CF1474F 1 2 3 4 ...
标签:计数DP,矩阵乘法,组合数学
来源:DP杂题选做
数据范围很小,启发我们大胆尝试多维DP或是矩阵乘法优化这类的(不过有些时候矩阵乘法优化DP是能发现一些性质使得矩乘复杂度变得更低,比如ARC154E)。
\(x\) 没用,给出的 \(a_i=0\) 也没用,先删掉这些元素。
剩下的序列是形如山峰一样的连续上升或连续下降,且相邻元素的差的绝对值一定是1,所以 lis 是连续的整数序列,长度就是最高位置-最低位置,可以做前缀和直接 \(O(n^2)\) 求出。
接下来考虑如何求方案数,因为 lis 一定是连续的,所以可以先剥离出这样的若干个极长段,具体的我们枚举左端点,找到最长的右端点使得他们的高度差恰好是 lis 长度。
设 \(dp[i][j]\) 表示现在 lis 填到了第 \(i\) 位,现在在第 \(j\) 个 \(a\) 中的位置,枚举下一位填在 \(k>j\) 可以做到 \(O(maxlen*n^2)\)。
观察同一段内的转移是相同的,只需要维护出转移矩阵的长度次方幂就可以做到 \(O(n^3logn)\),因为这样的连续段最多有 \(O(n)\) 段。所以复杂度为 \(O(n^4logn)\)。
注意上述做法前提是 lis 长度>1,所以下降序列需要特判。
还有 \(O(n^5)\) 的组合做法,可以参考博客。
2.7
CF1152F2 Neko Rules the Catniverse
标签:计数DP,矩阵乘法
来源:DP杂题选做
小数据范围版本的 \(n\) 只有 \(1e5\),而此题有 \(1e9\) 的数据范围,并且 \(k\) 和 \(m\) 的范围非常小,这启发我们用矩阵乘法优化DP。
先考虑朴素DP,本题要求序列中的数两两不同,所以按照序列位置 DP,并不好做,换个角度从值域进行DP。
假如没有第三个要求,那么可以设 \(dp[i][j]\) 表示已经跑了 \(1\) 到 \(n\) 的值域,填了序列的 \(j\) 个位置的方案数,转移分第 \(i+1\) 位是否加入序列讨论。
现在加上第三个要求,因为 \(m\) 非常小,按照[SDOI2009]学校食堂的套路设计状压DP。
设状态 \(dp[i][j][s]\) ,\(i,j\) 含义同上,\(s\) 表示 \([i-m+1,i]\) 之内选择的状态,转移的时候需要注意 \(i+1\) 被选时需要考虑 \(s\) 中选择的数的数量,因为 \(i+1\) 可以被接在其中任意一个后面,所以转移系数为 \(s\) 中数的数量+1(因为可以在所有数前面)。
写完 \(dp\) 转移式后发现转移过程与 \(i\) 完全独立,直接用矩阵快速幂优化即可,复杂度 \(O((k*2^m)^3logn)\),常数较大,不过时限很宽裕。
终于自己独立做出一道 CF3000+ 的题(虽然是刚好3000吧)。
CF1523H Hopping Around the Array
标签:最优化DP,倍增
来源:DP杂题选做
题面的操作可以简化为每次可以选择花费1从 \(i\) 走到 \([i+1,i+a[i]]\) 中的某个值或花费0走到 \(i+1\),总过程后者次数不能超过 \(k\)。
朴素DP可能会下意识想设状态表示从 \(i\) 开始花费 \(j\) 代价走了 \(k\) 个0操作能走到的最远位置,但是这不一定是最优,也许我们可以在这段路程中花费1代价进行一次走到 \(p+a[p]\) 的操作,这个可能更优,而不一定能更新到上述状态设计中 \(i\) 位置花费 \(j+1\) 的最远位置。
根据刚才的反例可以重新设计状态为从 \(i\) 开始花费 \(j\) 代价走了 \(k\) 个0操作过程中走到的 \(p+a[p]\) 最大的 \(p\),这个状态就可以避免上述问题的产生。
状态数 \(O(n^2k)\),状态转移需要做个类似背包的转移,枚举上一层走了 \(i\) 个0和 \(j\) 个0用背包拼出来这一层的 \(i+j\),转移复杂度 \(O(k)\),复杂度 \(O(n^2k^2)\),不足以通过。
考虑任意的 \(j\) 一定能表达为若干非零二次幂和的形式(特判0),于是用倍增优化,将状态中的 \(j\) 定义为花费 \(2^j\) 代价。
状态数变为了 \(O(nklogn)\),转移 \(O(k)\),预处理复杂度 \(O(nk^2logn)\)。
接下来是询问,首先特判 0 代价和 1 代价,因为我们的状态设计是之后还能再走1步 \(p\) 到 \(p+a[p]\),所以倍增时基础花费是 2。
之后就是类似倍增的查询就好了,单次查询复杂度 \(O(k^2logn)\),总复杂度 \(O((n+m)k^2logn)\)。
2.9
[ZJOI2009]染色游戏
标签:博弈
来源:博弈杂题选做
翻硬币游戏的模板题,之前做过类似的翻硬币模型。
详细记录下翻硬币模型。
基础翻硬币模型的定义:有一行若干个硬币,每个硬币区分正反面且有初始状态,两个人轮流操作,每次操作可以选取若干个硬币翻转正反面,唯一需要保证的是操作的最右边的硬币必须是从反到正,无法操作者败,求是否存在必胜策略。
当然你可以变成矩阵,限制变为最右下角,或者更高维度亦可。
结论是整个游戏的SG值等于所有反面朝上的硬币的SG值。
证明复杂抽象,至少OI现阶段记住结论能用上就好。
至于SG值一般是打表找规律,一般来讲会和二进制有联系。
2的倍数很容易看出。如果是lowbit的话需要自己观察,建议如果碰到这种题最好打出一个lowbit的表,一维的就是 lowbit(i),二维就是 lowbit(i * j)这类的,其中 $ * $表示二元运算符。
回到本题,通过打表可以得到SG函数的表达形式,直接预处理做,证明可以看lg博客。
整理这道题主要是为了整理这个模型,感觉算博弈论里比较常见的,而且SG函数合并是求其异或和,可以用数据结构维护,也可以出成数据结构题。
[SNOI2020] 字符串
标签:后缀自动机,贪心
来源:字符串杂题选做
修改后缀可以改为匹配最长公共前缀(lcp),暴力的话可以直接建图跑二分图最大匹配。
分析性质:把两个串插入trie树,那么他们trie内终止点的lca处的节点所代表的串就是他们的lcp。
但是把所有串插入trie复杂度不对,那么上后缀树就好,因为我们是求前缀,所以建反串的SAM即可。
剩下的就是匹配,可以在插入时把对应节点打上标记,那么在遍历后缀树的时候尽量在深处就合并,剩下的再考虑往父亲方向走,容易证明贪心正确性。
把这道题写出来主要是为了提醒自己记得后缀自动机本质是压缩trie,这样在分析性质时就可以先在trie上暴力想再放到SAM上,可能会容易些。
写过这题后看标签还有树形DP的tag,细想后缀树也是能出树形DP题,很恐怖。
2.10
CF1147C Thanos Nim
标签:博弈
来源:博弈作业
自己的想法:感觉石头可以看做三类:=0,=1,>1,于是设 \(sg[i][j]\),表示当前局势有 \(i\) 堆=1和 \(j\) 堆>1的 sg 函数值,但是错的比较离谱。
自己的想法与正解说实话毫不相干,果然还是博弈做的少。
正解考虑当最小堆的数量 \(k\leq \frac{n}{2}\) 时,先手必胜,反之必败。
证明:
可以先把序列排个序。
当 \(k\leq \frac{n}{2}\) 时,先手可以把后一半取成和前一半一样的形态,之后模仿后手操作就可以做到必胜。
当 \(k> \frac{n}{2}\) 时,先手无论如何至少取到一个最小堆,那么此时最小堆更新,并且数量一定 \(\leq \frac{n}{2}\),那么就变成了后手必胜的局面,所以先手必败。
博弈论先猜结论再反证挺常见的,但是猜结论需要见题多感觉好,而且也可以打表来找一些规律。
猜结论的话很多情况都需要先后手互相模仿操作,或许可以从一方选择了最优操作,另一方模仿也不会更差来考虑。
不过对于本题打表数据量太大,跟着感觉猜结论或许是比较好的方法。
[ABC206F] Interval Game 2
标签:博弈
来源:博弈作业
我们定义一个局面是 \([l,r]\),且 \([l,r]\) 没有任何线段存在。
那么可以选择一个属于这个区间的线段 \([a,b]\),向下递归 \([l,a-1]\) 与 \([b+1,r]\) 两个子局面,根据sg函数的定义有 \(sg([l,r])=mex_{[a,b]\in[l,r]}{sg([l,a-1])\otimes sg(b+1,r)}\)。
直接记忆化搜索,复杂度 \(O(Tn^3)\)。
独立做出来的sg函数题,主要考察对sg函数定义和运算符号的理解,算是基础题。
JZYZOJ 2724
标签:博弈
来源:博弈作业
二分图博弈模板。
二分图博弈的一般形式:状态可以划分为 \(A,B\) 两个集合,任意的转移都是跨过集合的,不存在集合内的转移边,两个玩家操作,从一个状态出发,不能经过曾经访问过的状态,不能转移者输。
结论:任意最大匹配都包含的点先手必胜,否则先手必败。
证明:
假设求出了一组最大匹配,现在选择一个非匹配点作为初始状态,下一步一定走到匹配点(否则找到了新的增广路,不满足最大匹配定义),后手接着沿匹配边走,而先手之后只能走匹配点(否则同上会找到新的增广路),因为这是一组匹配,所以先手最后无路可走,这个状态就是先手必败。
如果起始状态是匹配点,那么先手执行上述后手的策略,容易得到先手必胜。
求解的话可以匈牙利可以网络流,网络流需要讨论残余网络稍复杂一些,这里简述匈牙利的做法。
先用匈牙利跑一组最大匹配,这时可以确定非匹配点都是先手必败,然后从所有先手必败点出发,他们经过转移边到达的状态根据上文可得都是先手必败状态,为了保证复杂度打上访问过标记即可,复杂度 \(O(nm)\),\(n\) 是点数,\(m\) 是边数。
UPD:
使用 Dinic 求解网络流后构造还是比较容易的。
考虑正反求两遍最大流,之后就可以根据判定网络流中某个点是否一定存在某个最大匹配的必要条件来求解每个点的答案,证明在OI中不太重要。
[hihocode 1466]重复旋律9
标签:博弈,后缀自动机
来源:博弈作业
往末尾添加字符可以看做SAM上的转移,于是这个游戏对应的图就是SAM,因为SAM是DAG所以SG值可以拓扑排序求出。
现在需要求出字典序(这里的字典序是相当于先比较A再比较B,题面没写清楚)第 k 小的先手必胜状态,因为是两个串所以先手必胜前提是两个串在SAM上对应节点的sg值异或和不为0。
那么这种问题一般做法是求出当前拼出来的前缀所有可能的后缀有多少种方案,与 K 比较,如果大于就继续向后填,直到填到等于。
本题同样用这种解法,求出每种子串后缀的方案数,注意要按sg值分类,先把A串拼出来,A串拼的时候需要考虑B的所有子串都能作为某种意义的后缀,都需要考虑在内。拼出A串后再拼B串,B串的限制就只剩下不能与已经拼好的A的sg值相等了。
复杂度 \(O(n*|V|)\),\(|V|\) 是字符集大小。
2.12
[AGC010F] Tree Game
标签:博弈
来源:博弈杂题选做
本题体现了博弈题的从子问题出发的一种思路。
只有一个点肯定是先手必败,不妨考虑只有两个点的情况,假设先手点是 \(x\),后手点是 \(y\),先手必胜当且仅当 \(a_x>a_y\),证明显然。
不妨扩大问题规模,现在把题目给出的树变成先手点为根的有根树,不妨定义一个点 \(x\) 的胜负状态是当游戏只在 \(x\) 的子树内进行,这样定义是因为任意游戏路径都能找到某个点的子树来描述。特别的,叶子先手必败。
联想我们刚才只有两个点的结论,我们猜结论:当且仅当 \(x\) 存在一个先手必败态的儿子石子数小于 \(a_x\) 时,\(x\) 的状态是先手必胜。
先从正面考虑,如果存在一个这样的儿子,那么仅考虑这两个点先手一定能让后手转移到这个儿子上,因为这个儿子是先手必败态,所以此时后手必败,那么先手必胜。
再考虑反面,叶子的时候显然先手必败,否则先手一定想尽量让后手走到先手必败的儿子上,但是因为所有先手必败的儿子都无法满足让后手留在此处,后手总能借助多出来的石子回到 \(x\) 节点上,故此时先手必败。
直接枚举一遍根按上述规定遍历一遍树即可,复杂度 \(O(n^2)\)。
SP11414 Combat on a tree
标签:博弈,trie
来源:博弈杂题选做
博弈与数据结构结合的好题。
从题目描述可以看出这是一个公平组合游戏,所以可以通过求 sg 函数值判断胜负。
先考虑如何判断先手必胜。
为了方便,定义点 \(x\) 的 sg 函数值为 \(x\) 子树内的胜负情况。
根据定义和题目操作,可以通过枚举 \(x\) 子树内的所有白点(如果 \(x\) 是白点也要算入),删去白点到 \(x\) 路径上的所有点,这个局面形成了一个森林,那么 \(x\) 的sg值就是所有森林的 \(sg\) 值的 mex,森林的 sg 值就是所有树的 sg 值的异或,暴力做可以做到 \(n^3\) 到 \(n^2\) 的复杂度。
考虑优化,在每个节点维护一个trie树表示子树内所有森林的 sg 值,那么转移就可以通过在 trie 树上打标记来做,往根更新就是合并 trie,都是动态开点数据结构的基本操作了,求 mex 可以通过类似线段树二分的操作,先看左子是否是满二叉树,是的话向右子递归,否则去左子。
这样判断先手必胜就可以做到 \(nlog|V|\) 的复杂度,\(|V|\) 是 sg 函数值的上界,有向图游戏中不难发现上界是 \(maxdeg+1\),本题中就是 \(n\)。
接下来是求所有先手必胜点,如果存在某个子树的后继状态是必败 (从根递推的 \(sg=0\)),那么他就是先手必胜点,直接反向遍历一遍就好,复杂度 \(O(n)\)。
2.15
CF1174F Ehab and the Big Finale
标签:交互,重链剖分
来源:交互杂题选做
根据只能交互36次以及数据范围,猜想操作次数上界是 \(2logn\)。
看到交互都与路径相关,联想到树剖,于是可以猜测是每次跳重链通过两次询问得到接下来要走的点。
那么从根节点1出发,先特判1就是目标,然后用一个变量 \(lst\) 记录每次链顶到目标的距离,然后查询重链低到目标的距离 \(d\),此时有两种可能:
1 .\(lst+d\) 是这条重链的长度,那么目标点就在当前链上,直接根据差值算出在重链上坐标。
2 .否则,说明目标点在重链某个点的轻儿子子树内,那么计算一下这个点是谁,通过第二种操作得到下一步跳到的轻儿子,重复上述步骤即可。
容易发现每条重链最多两种操作各使用一次,所以询问次数一定小于等于 \(2logn\)。
2.16
JZYZOJ 4741
标签:回文串,hash,二分图
来源:教练在作业里加的神秘题
首先放结论:一个长度为 \(n\) 的字符串的本质不同回文子串数量不超过 \(n\)。
证明考虑回文自动机的每个节点对应一个本质不同的回文子串,而回文自动机最多会有 \(n+2\) 个节点,除掉奇偶两个根节点那么就是最多 \(n\) 个本质不同的回文子串。
那么可以通过 hash/PAM 等等求出来所有回文子串,接下来可以用 hash/SAM 求出这些子串间的包含关系,容易发现有连边一定是短的串向长的串连边,那么这张图就是个 dag 。
我们要做的就是求出来这个 dag 的最大点集,使得任意两点不可达。
那么相当于我们要求的是这个 dag 的最小路径覆盖(即选最少的不交路径覆盖 dag)。那么根据二分图理论最小路径覆盖=点数- dag 对应二分图的最大匹配,可以跑拆点二分图,也可以直接把 dag 看做二分图跑最大匹配即可,在 cafard 的帮助分析下得到这两种做法等价(至少在本题中)。
复杂度:求回文子串 \(O(n^2)\)-\(O(n)\),求包含关系 \(O(n^3)\),求最大匹配 \(O(m\sqrt n)\),瓶颈主要在求包含关系上。
2.17
CF1110G Tree-Tac-Toe
标签:博弈,构造
来源:博弈杂题选做
这题的操作是树上黑白染色,胜负终止态不是常规的sg函数就能求出的,所以这题是大力分类讨论。
分讨肯定是要尽量最小化讨论情况数,本题终止态是一方染出三个同色点,先假设所有点都没提前染色。
感性去想点的度数越大先手越容易获胜,分析后发现度数 \(>3\) 的时候先手必胜,先手把这个点染色,那么这个点剩下周围一圈至少4个点先手总能再染色两个。
再考虑度数 \(\leq 3\) 的情况,如果是链不难发现一定平局,否则图中存在度数为 3 的点,这些点对我们来讲更重要。
分析这些点连边情况,如果一个度数为 3 的点伸出了至少两条长度 \(\geq 2\) 的链,那么先手选了中间的点,后手最多堵住这些链的其中一条,先手可以在后手没堵住的链上染色,从而先手必胜。
那么剩下的情况只有所有度数为 \(3\) 的点最多伸出一条长度 \(\geq 2\) 的链,通过画图可以发现此时最多只存在两个度数为 3 的点,而且一定是在链的两端,形成了 "H" 的形状,这时候只需要讨论两个点之间的路径点数,通过分析可以得出为偶数时先手必胜,否则平局。
上面已经把没有提前染好色的点的情况全部讨论完了,那么有提前染色好的白点就需要特殊构造一下,额外给白点连出一个下图的形状,然后看做没有提前染色。
手玩一下发现此时先手如果选择把1号点染色,之后两个人根据最优策略后手会染色 \(2\) 号点,剩下的 \(3,4\) 号点要么不再操作,要么后手选择其中一个后先手再选择另一个,此时先后手顺序没有变化,而 \(1\) 号点也变成了白色,相当于两个人各多走两步且对其他节点没有产生影响,所以这样构造是正确的。
那么直接根据三种判定规则模拟即可,复杂度线性。
P4707 重返现世
标签:min-max 容斥,期望
来源:min-max 容斥作业
关于 min-max 容斥及其扩展可以参考博客
min-max 容斥是可以扩展到期望的。
原题相当于求 \(Emin_k(S)\),可以翻转过来变成 \(Emax_{n-k+1}(S)\),这样做的原因是本题中求 \(Emin(S)\) 更简单。
这里的最小值可以理解为每个元素有一个出现时间,这些时间的最小值,就可以从期望的角度理解。
那么 \(Emin(a)=\sum_{i=1}^{\infty}p_a(1-p_a)^{i-1}=\frac{1}{p_a}\),\(Emin(S)=\frac{1}{\sum_{a \in S}p_a}\)
利用 min-max 容斥,把原题变为 \(Emax_k(S)=\sum_{\emptyset \neq T\subset S}C_{|T|-1}^{k-1}(-1)^{|T|-k}Emin(T)\)。
现在可以 \(O(n2^n)\) 做,继续优化。
设 \(f_{i,j,k}\) 表示前 \(i\) 个元素,\(\sum {p}=j\),\(\sum_{T}C_{|T|-1}^{k-1}(-1)^{|T|-k}\) 的值,转移讨论 \(i\) 是否属于 \(T\)。
\(i\notin T\),则 \(f_{i,j,k}\leftarrow f_{i-1,j,k}\)
\(i\in T\),则在 \(f_{i,j,k}\leftarrow f_{i-1,j,k}\) 的基础上,额外考虑 \(f_{i,j,k}=\sum_{i\in T}C_{|T|-1}^{k-1}(-1)^{|T|-k}\)。
把 \(i\) 从 \(T\) 里面去掉,那么 \(\sum {p}=j-p_i\),那么就变成了
现在复杂度变成了 \(O(nmk)\),用滚动数组优化空间即可。
[HEOI2016/TJOI2016]排序
标签:线段树,二分
来源:杂题选做
本题有在线的线段树分裂做法,这里暂不讲解,下文讲解离线二分的做法。
如果是对只有0/1元素的序列排序,显然是可以用线段树做到 \(O(logn)\) 的,我们可以枚举最终位置上的数字 \(x\),然后把排列中 \(\geq x\) 的位置赋值成 1,其他赋值成 0,全部操作完后最终位置上是 1 那这个数字就合法,找到最大的即可。
感性理解就是合法与不合法恰好把序列分成前缀和后缀,也就是单调性,理性分析考虑排序的时候 1 的实际含义是大于等于当前枚举的数字,所以对于 \(x<y\),\(y\) 能合法的时候最终序列的 1 都不会变成 0,那么 \(x\) 也一定能合法。
那么每次判断就可以做到 \(O(mlogn)\),外层二分总复杂度可以做到 \(O(mlog^2n)\)。
[HAOI2015]按位或
标签:min-max 容斥,FWT
来源:min-max 容斥作业
首先可以看出来是求 \(Emax(S)\),容斥后变为求 \(\sum_{\emptyset \neq T\subset S}Emin(T)(-1)^{|T|-1}\)
求 \(Emin(S)\) 相当于 \(S\) 中有元素变为 1 期望时间,根据期望的公式有 \(Emin(S)=\sum_{i=1}^{\infty}iP(min(S)=i)\),其中 \(P(min(S)=i)\) 表示恰好在第 \(i\) 秒出现 1 的概率。
前 \(i-1\) 秒都没出现,第 \(i\) 秒恰好出现,不难得出概率为
那么期望也就能算了。
这个式子是对 \(S\) 的补集求子集和,用 FWT 即可。
复杂度 \(O(n2^n)\)。
2.20
[AGC017D] Game on Tree
标签:博弈
来源:博弈作业
结论题,记住结论就好。
树上公平博弈游戏的sg值计算方式:\(sg(x)={xor}_{y\in son(x)}(sg(y)+1)\)
证明可以参考这里,不过oi里面记结论大概就足够了。
[APC001F] XOR Tree
标签:状压DP,位运算
来源:杂题选做
路径异或的操作可以抽象为树上差分,但本题的权值是边权,所以需要边权转点权,具体的,让每个点的权值为与他相邻的所有边权异或和,那么每次路径异或就可以看做只把两个端点异或上操作的权值,因为路径上的其他点都被恰好修改了两条相邻的边的权值,而端点只有一条。
猜想所有点权为0是所有边权为0的充要条件,充分性不难证明,必要性考虑确定某个点为根后从叶子往上归纳,容易发现点权都是0的时候边权也必须都是0。
现在问题转化为了给出一个长度为 \(n\) ,值域为 \(15\) 的序列,每次可以选择两个数删去,如果这两个数不同则加入他们的异或和,最小化使得所有元素都为0的操作次数。
因为本题的特殊性,所有元素的异或和为0(因为每条边的边权都被异或两次),所以一定有解。
显然,一定优先操做相同的两个数,那么之后每种值最多剩下一个元素。
因为只有15种非0权值,所以考虑状压DP,设 \(f_s\) 表示集合状态为 \(s\) 时最少操作次数,要求 \(s\) 满足元素异或和为0,初始有上界 \(f_s=|s|-1\),(每次选的两个数都是不同的)。
DP过程考虑为了最小化一定是把当前集合分裂成两个不交集合 \(t(t\subset s)\) 和 \(s\setminus t\),那么就有 \(f_s=min f_t+f_{s\setminus t}\),枚举子集,复杂度 \(O(3^{15})\)。
总上,复杂度 \(O(n+3^{15})\)。
[USACO21OPEN] Routing Schemes P
标签:BEST定理,矩阵树定理
来源:杂题选做
复习矩阵树定理相关内容的题。
每条边恰好覆盖一次的要求让我们联想到欧拉回路,如果把起点和终点都连向一个新建的超级点,那么会发现这些路径会形成这个新图的欧拉回路,于是这道题就变成了这个新图的欧拉回路计数。
1 . 有向图 \({G={V,E}}\) 的欧拉回路数量为 \(T_{s}(G) * \prod_{i\in V}(d_i-1)!\)
其中 \(T_{s}(G)\) 表示以某一点 \(s\) 为根的内向生成树的数量,\(d_i\) 表示 \(i\) 的出度。
2 . 有向图 \({G={V,E}}\) 以 \(s\) 为起点的欧拉回路数量为 \(T_{s}(G) * (d_s)! * \prod_{i\in V,i\neq s}(d_i-1)\)
上面的两个定理都可以用矩阵树定理求解,有向图生成树的矩阵树定理可以参考文章,需要注意本题需要把孤立点去掉。
复杂度 \(O(Tn^3)\)
2.22
CF979E Kuro and Topological Parity
标签:DP
来源:?
练习一下分类讨论。
看到 \(n\) 很小,大胆增加状态维数。
因为路径是黑白相间并且最终要看路径总数的奇偶性,所以设计状态为 \(f_{i,a,b,c,d}\),表示前 \(i\) 个点,四类点的数量为 \(a,b,c,d\) 时的方案数,四类点其中一类是该点为黑色且以该点为终止点的路径有奇数条,其他三类类似,令其分别为奇白,偶黑,偶白。
已经有了 \(i-1\) 个点,现在新加入一个点,假如是白点(黑点对称转移),有如下情况:
1 . 新点为奇白,需要拿出来奇数个奇黑和任意个偶黑,奇数个奇黑根据组合数公式可以算出是 \(2^{a-1}\),任意个偶黑是 \(2^{b}\),其他任意分别为 \(2^c\) 和 \(2^d\),全部乘起来就是 \(2^{i-2}\)。
2 . 新点为偶白,需要拿出来偶数个奇黑和任意个偶黑,同上计算为 \(2^{i-2}\)。
我们发现上面两类都是建立在存在奇黑上的,如果不存在那么新点只能成为偶白,转移为 \(2^{i-1}\)。
状态只需要记录 \(i,a,b,c\) ,\(d\) 可以直接计算得到,状态数 \(O(n^4)\),转移 \(O(1)\),复杂度 \(O(n^4)\)。
发现上面的转移系数只和 \(i\) 有关,四类点只需要考虑奇黑和奇白的存在性,进一步省下来状态,再多记录一维表示当前总路径数量的奇偶性,状态数 \(O(2^3*n)\),转移 \(O(1)\),复杂度 \(O(2^3*n)\)。
2.24
[AT codefestival 2016 H]Tokaido
标签:DP
来源:?
非常强的性质题。
首先转化博弈背景,容易发现当前操作者如果右边相邻格是空的那么下一步一定走的是右边相邻格,换句话说两个人交替走若干连续段,可以写出基础DP,设 \(f_{i,j}\) 表示第 \(i\) 个位置是 \(j=0/1\) 选的时候的终止局面最优值,根据策略写出伪代码。
f[n][0]=a[n]; f[n][1]=-a[n];
for(i, n-1, 2) for(j, i+1, n)
f[i][0]=min(f[i][0], f[j][1]+sum[j-1]-sum[i-1];
f[i][1]=max(f[i][1], f[j][0]-sum[j-1]+sum[i-1];
return a[1]+f[2][1];
不难发现 \(f_{i,0}\) 与 \(f_{i,1}\) 互为相反数,省去一维。
f[n]=a[n];
for(i, n-1, 2) for(j, i+1, n)
f[i]=min(f[i], -f[j]+sum[j-1]-sum[i-1];
return a[1]-f[2];
按套路记录 \(mn=min\{sum_{i-1}-f_i\}\)。
f[n]=a[n]; mn=sum[n-1]-f[n];
for(i, n-1, 2) f[i]=mn-sum[i-1], mn=min(mn, sum[i-1]-f[i]);
return a[1]-f[2];
现在已经做到了单次询问线性,可以通过 700/1600。
继续观察,发现不需要 \(f\) 数组。
mn=sum[n-1]-a[n];
for(i, n-1, 3) mn=min(mn, 2*sum[i-1]-mn);
return 2*a[1]-mn;
现在 DP 的部分看上去已经走到尽头了,现在看一下数据范围限制,有一个很重要的 \(\sum A_{i}\leq 1e6\)。
虽然 \(X\leq 1e9\),但是当 \(sum_{n-1}-X\leq 0\) 的时候,不难发现 \(mn\) 不再改变,所以只需要考虑 \(X< sum_{n-1}\) 的情况。
一个方向是离线询问,另一个方向是降低单次询问复杂度,这里讲后者。
首先考虑 \(mn\) 产生变化的条件:\(2*sum_{i}-mn<mn\) ,即 \(mn>sum_i\),那么可以按点权建图,把每个点指向小于他的 \(sum\) ,暴力建图是 \(O(n^2)\) 的,但是不难发现只需要找出来最近的 \(sum\) 建边仍然满足传递关系,进一步分析发现图是森林(其实不是森林也能做),那么找到每棵树的树根遍历一遍就可以在线性时间内求出每个数最后会变成什么,单次询问就可以做到 \(O(1)\) 。
2.27
CF938G Shortest Path Queries
标签:线性基,并查集,线段树分治
来源:线性基杂题选做
模拟赛被线性基诈骗题搞炸了,做一做线性基题。
不看修改,只是单纯求最短异或路径(非简单路径),可以直接用 [WC2011]最大XOR和路径 做。
那么加上修改后就线段树分治边的存在时间就好,因为题目保证操作合法所以不需要分类讨论。
唯一复杂一点的大概是求两点间任意异或路径,用边带权并查集维护每个点到并查集根的异或距离,合并时讨论一下根的变化情况,因为题目保证图连通所以直接分别查两个点到并查集根距离再异或。
因为是线段树分治,所以并查集和线性基都要求可撤销,用内存池记录一下。
复杂度 \(O(nlog^2n)\)。
AtCoder Odd Subrectangles
标签:线性基
来源:线性基杂题选做
先考虑一个简单的问题:给出 \(n\) 个非负整数,求出异或和为 0 的子集的数量。
把所有的元素插入线性基,设线性基大小是 \(s\),答案就是 \(2^{n-s}\),即在非线性基元素中任意选总能用线性基做出来和他相等的集合,易证充要。
回到本题,加入把这个矩阵看做 \(n\) 个 \(m\) 位的二进制数,现在选出来了若干个,题面的要求容易让我们联系到异或。
可以发现,除非异或的结果没有0,否则任意钦定一个为1的位置,容易发现其他的位置任意选择的方案都能通过控制钦定的位置选或不选来控制 1 的数量是奇数。
那么对于非0的异或结果,方案数就是 \(2^{m-1}\)。
于是求补集,插入线性基后,答案即为 \(2^{m-1}(2^{n}-2^{n-s})\),复杂度 \(O(\frac{n^2m}{w})\)。
2.28
[AGC038E] Gachapon
标签:min-max 容斥
来源:min-max 容斥作业
被概率期望DP橄榄了。
题目所求可以看做最后一个元素达到 \(B_i\) 要求的期望时间,或者说所以元素达到要求的期望时间的最大值,因此可以用期望意义的 min-max 容斥,转为求集合内所有元素达到要求的期望时间最小值,即有一个元素达到要求就停止。
如果 \(B=1\) ,那么就是重返现世的部分分,但 \(B\neq 1\) 。
首先可以做一步算期望变为算概率的转化:选到集合内元素的期望步数可以很容易算出,具体的是 \(\frac{\sum a_i}{\sum_{i\in T}a_i}\),可以用等比数列求和推导,这里省略。
那么所有没达到要求的状态一定是形如 \(K=\sum_{i\in T}c_i(c_i<b_i)\) 的形式,而且每一种在期望意义下都会被经历到,所以可以求出所有状态的概率,乘上一步的期望值(就是上文的式子),就是我们所求的 \(Emin(T)\)。
具体的,对于某个状态的概率为 \(\frac{K!}{\prod_{i\in T}c_i} \times \prod_{i\in T}{\frac{a_i}{\sum_{i\in T}{a_i}}}^{c_i}\)。
现在把式子全部列出来入下:
可以发现 \(\sum_{i\in T}a_i\) 和 \(\sum_{i\in T} c_i\) 是不容易维护的,所以考虑独立出来作为状态,设计 \(dp_{i,j,k}\) 表示所有的集合 \(T\subset {1,2,……,i}\),\(\sum_{i\in T}a_i=j\) 且 \(\sum_{i\in T} c_i=k\) 的某种值之和,观察得到需要维护 \((-1)^{|T|-1}\frac{1}{c_i!}a_i^{c_i}\),转移枚举是否把 \(i+1\) 加入集合。
复杂度可以思考任意两个不同的 \(\sum_{i\in T}c_i\) 只会产生一次合并,所以复杂度是 \(O(\sum{a_i}(\sum{b_i})^2)\),转移是背包形式空间复杂度可以优化到 \(O(\sum{a_i}\sum{b_i})\)。
[UNR#1] 合唱队形
标签:min-max 容斥,根号分治
来源:min-max 容斥作业
首先转化题意:现在有 \(n-m+1\) 个字符串,每个字符串的每个字符是在给定字符集中随机选取,每次随机确定这些字符串中的某个字符,当存在一个字符串与给定串相等的时候结束,问期望时间。
这个等价于每个字符串的期望相等时间的最小值,于是可以用 min-max 容斥转化为期望的最大值,即钦定的子集中的字符串都变成和给定串相等的时间。
对于 \(Emax(T)\),可以先求出子集中一共有 \(w(T)\) 个特殊的字符,那么就相当于在所有 \(tot\) 个字符中每次随机挑元素,把这些特殊的字符都挑出至少一次的期望时间,这个可以参考[SHOI2002] 百事世界杯之旅得出为 \(\sum_{i}^{w(T)}\frac{tot}{i}\)。
当 \(n-m+1\) 比较小的时候,可以直接跑 min-max 的定义式,复杂度 \(O(n^22^{n-m+1})\)
当 \(m\) 比较小的时候,可以设计状压DP,用 \(g_{i,j,s}\) 表示前 \(i\) 个字符串 ,\(w(T)=j\),前 \(i-1\) 个人中后最多 \(m\) 个字符串是否被纳入考虑的状态是 \(s\) \((-1)^{|T|-1}\) 之和,之所以只考虑最多 \(m\) 个是因为两个字符串的位置相差大于等于 \(m\) 时不会产生交集不会影响 \(w(T)\) 。
提前预处理 \(f_{i,s}\) 表示当状态为 \(s\) 时加入字符串 \(i\) 对 \(w(T)\) 产生的贡献,总复杂度为 \(O(n^32^m)\)。
对 \(2^m\) 根号分治即可,复杂度大概为 \(O(n^32^{\frac{n}{2}})\)。
UOJ422 小Z的礼物
标签:min-max 容斥,轮廓线DP
来源:min-max 容斥作业
题目所求为所有关键点被收集到的期望时间的最大值,用 min-max 容斥变为求子集内的关键点被收集到的期望时间的最小值,即任意一个关键点被收集到的期望时间。
设当前子集的关键点涉及到的点对有 \(w(T)\) 个,\(n*m\) 的网格一共有 \(tot=n*(m-1)+m*(n-1)\) 个点对,期望时间为概率倒数,即 \(Emin(T)=\frac{tot}{w(T)}\)。
\(w(T)\) 难以维护,考虑作为DP的状态,设 \(f_{i,j,k,s}\) 表示前 \(i\) 列 \(w(T)=k\),且 \(i-1\) 行的后 \(n-j+1\) 个数与第 \(i\) 行前 \(j\) 个数拼起来的选择状态为 \(s\) 的 \((-1)^{|T|-1}\) 的和,转移枚举当前点是否加入 \(T\),对 \(w(T)\) 的改变可以暴力分类讨论,情况只有四种。
复杂度 \(O(n^2m^22^n)\),空间复杂度可以滚动优化。
UOJ499 喂鸽子
标签:min-max 容斥,NTT
来源:min-max 容斥作业
可以看做 [AGC038E] Gachapon 的数据范围加强版,如果直接用那道题的DP,即使NTT优化也是 \(n^3klog(nk)\) 的,过不掉。
主要参考了这篇博客,公式太多不想再敲一遍了(ー=≡Σ( ε¦) 0)
这里做一些关于 min-max 容斥在期望意义下的小结。
一般来说,\(Emax\) 的定义是所有元素都满足某个条件,\(Emin\) 的定义是存在一个元素满足某个条件,第一步转化期望是最为重要的。
举个例子,每次进行区间覆盖,问覆盖整个数轴的期望时间,可以把数轴每个单位独立出来,n那么题目就是求 \(Emax\),转为求 \(Emin\),即子集内存在一个单位被覆盖的期望时间。
一般来说,这些题都是在一个大集合中以带权概率选择某个元素,所以要用到极限意义的等差数列求和来推导,比如在 \(n\) 个元素中选中特定的 \(k\) 个概率是 \(\frac{k}{n}\),通过极限意义的等差数列求和推导出期望是其倒数即 \(\frac{n}{k}\)。
这些只是辅助工具,min-max 容斥最精髓的地方在于设计概率期望DP,这些题目各有特点,只能仁者见仁智者见智了。
不过一个常见的思路是枚举 \(i\) ,计算 \(T\subset {1,2,……,i}\) 的某种价值 \(w(T)\) 之和,如果发现表达式中有形如 \(\sum_{i\in T}a_i\) 的形式,在数据范围不大的情况下不妨把这个独立出来设计成状态的一维,也许就能简化转移的表达式。
转移一般是枚举当前元素是否选进 \(T\) 中,并相应的处理处对于其他维度的增量,如果发现难以在线处理,不妨离线下来(这种东西应该没什么途径能强制在线吧)。
当发现某些集合的本质相同时,比如对于 \(|T|=k\) 的 \(T\) 本质相等,不妨改良一下 min-max 容斥的基本式,改良为 \(\sum_{i=1}^{n}(-1)^{i-1}C_{n}^{i}Emin(T)(|T|=i)\),这是只需要对于每种 \(|T|\) 求出一个 \(Emin(T)\) 即可,或许可以优化复杂度,而且多出来个组合数也许可以往EGF的方向发展。