2019 Moscow Workshop 题解
day1
【A√,D√,H,J,K,L,M】
水题;猥琐题。
【B√】
题意:有一个 \(w \times h\) 的桌面,上面有 \(N(\leq 11)\) 个球,每个球有一个半径 \(r\)。现在 \(1\) 号球以 \((vx,vy)\) 的方向前进,遇到桌的边界会完全弹性碰撞。问 \(10000\) 个单位长度内,它先撞到别的哪个球。
题解:看上去要圆与圆求交。一个经典的处理方式是:可以将关键的圆看成点,别的图形相应地做变化即可。在这里,桌面边界会往里缩,其他圆的半径会增加 \(r\)。处理 \(1\) 号球的碰撞时,只需处理点的反射。
【C√】
题意:对于 \(1 \leq A \leq B \leq 10^{18}\),记 \(k_i\) 为 \(A \sim B\) 数字中二进制第 \(i\) 位是 \(1\) 的数字个数。现在给出 \(k_i (i \leq 63)\),判断 \((A,B)\) 的有解性,如有唯一解同时给出解。
题解:从大到小考虑 \(k_i\)。每次考察 \([A,B]\) 是否跨越了 \(2^i\) 这条分割线。如果没有跨越,那么我们知道 \([A,B]\) 是在 \([2^i,...]\) 区间里一个长度为 \(k_i\) 的区间,继续递归下去求解。如果跨越了,根据 \(k_i\),我们可以直接定位出 \(B\) 的值(\(A\) 也可以通过二分来确定);注意上层递归下来时,可能有 AB 长度要求,必须同时符合才行。
【E√】
题意:给出一个最多 \(1000\) 项的多项式 \(F(x)=\sum a_i x^{b_i}\),其中 \(a_i \leq 10^{15},b_i \leq 10^9\)。已知 \(F(x)=F'(x)=0\),求符合要求的最小正整数解 \(x\) 或输出无解。
题解:由题意可证,\(x^2 | a_k\),其中 \(k\) 是次数最小的非零项。快速分解 \(a_k\) 后,直接枚举所有符合要求的 \(x\) 即可。check 时,可以给出一些模域;多个模域下为 \(0\) 可视为答案为 \(0\)。快速分解时,可以只枚举到 \(10^5\),剩下的质因子只可能是 \(P,PQ,P^2\),而只有第三者才有意义。
【F√】
题意:初始时有一个三个点的二叉树,“剪贴板”上也是这棵树。每次可以选择一个叶子,将其替换为剪贴板上的内容。每步操作完成后,可以选择将整棵树放入剪切板(不消耗步数)。给出一棵 \(N(\leq 1000)\) 个点的二叉树,问可以最少几步变成它。
题解:考虑最后一次复制后的图形。如果枚举了它的大小 \(k\),我们可以知道它的具体形状,也可以通过树哈希在 \(O(N)\) 的时间里,判断它是否可能。还会发现一个性质时,对于这个图形之前的小图形,因为能拼成这个,一定也能拼成总体。所以首先,我们可以枚举所有 \(N-1\) 的约数 \(k-1\),check 一遍以 \(k\) 为模板是否可行。如果枚举了最后的图形,我们要知道从初始开始最少几步到它,这可以通过对所有合法的约数做一遍预处理DP后得到。复杂度为 \(O(K^2+NK)\),\(K\) 是 \(N\) 的约数个数。
【G】
连通性DP。
【I√】
题意:有 \(R(\leq 128)\) 行格子,每行 \(C(\leq 16)\) 个。给出 \(R\) 个长度不超过 \(C\) 的字符串,将它们依次填在每一行,使得字符串字符的相对顺序保持不变(有些位置为留空)。定义一个有字符的格子的价值为:其上下左右和它一样的格子个数。求可能的最大的总价值。
题解:很容易想到按行转移,每行最多会有 \(C_{16}^8\) 中状态。看上去状态数不多,但是显然不能支持平方的转移。比赛的时候想到了各种优化转移的方法,甚至要利用 trie,但是效果都不好。
其实只要按格子一格一格转移(类似于轮廓线DP),这种表示方法也支持快速算代价,复杂度就是 \(RC2^C\)。
day2
【A√,B,G,J,K】
水题/模拟题;待补
【C√】
题意:给出平面上 \(N(\leq 100)\) 个点,没有三点共线的情况。要画 \(\lceil \frac{n}{2} \rceil\) 条直线将平面划成一些区域,使每个点仅属于一个区域。
题解:先找到任意一条直线,将点集划成差最多为 \(1\) 的两部分。每次操作时,左右剩下的点各做一个凸包,取凸包的上(同侧)公切线,将其稍稍向下平移,即可做出一条将这两个点都分开的直线。每次删掉两个点继续操作,总复杂度为 \(O(N^2)\)。
如何求两个凸包的公切线?。左右凸包各选择一个点,每次固定一个点 \(A\),如果 \(AB\) 和凸包 \(b\) 在顶点 \(B\) 外也有交,就把 \(B\) 继续往一侧移动。交替迭代,一定是向某条公切线靠近的。细致点实现,复杂度 \(O(N)\)。
【D√】
题意:求 \(N\) 个点的 每个连通块最多只有一个环的 带标号图的个数。
题解:带标号无根树个数是 \(N^{N-2}\),考虑如何计算带标号基环树的个数。假设一共有 \(N\) 个点,环长是 \(M\)。对除环以外的 \(N-M\) 个点做 \(prufer\) 序列。该序列最后一个点必须是环上的点(因为做到的最后一个点的父亲必然在环上),其他随意。所以方案数是 \(M \times N^{N-M-1}\)。再乘上 \(\frac{(M-1)!}{2} \times C_{N}^M\) 即为 \(N\) 个点环长为 \(M\) 的带标号基环树个数了。最后做一遍背包即可得到答案。
【F√】
题意:有三只怪兽,攻击为 \(A_i(\leq 10^9)\),血量为 \(B_i(B_1 \leq 10^{18},B_2,B_3 \leq 100)\)。每轮开始时,所有活着的怪兽对你造成等同于它们攻击力和的伤害。第 \(i\) 轮时,你可以选择一只怪兽,对其造成 \(i\) 点伤害。怪兽血量非正时死亡。问打完所有怪兽后最少受到多少的伤害。
题解:假设每轮都在打第一只怪兽。我们可能会在某几轮,“抽空”去打另外两只。设 \(f_{i,j,k}\) 表示到了前 \(i\) 轮,二三两只怪兽分别受到了 \(j,k\) 点伤害时,我们受到的最小伤害。注意这种表示下,如果 \(k \geq B_2\) 或 \(j \leq B_3\) 也是有意义的,因为我们要根据 \(i,j,k\) 算出,我们已经对第一只怪兽造成了多少伤害了;这样也可以快速算出转移时我们每轮受到的伤害和。
当超过 \(102\) 轮后,另外两只怪兽要不已经死了,要不被留在最后再攻击。
【H√】
题意:给出两棵 \(N(\leq 10^5)\) 个点的带边权的树。求 \(\sum_{i,j} Ad_{i,j} \times Bd_{i,j} \mod 10^9+7\)。其中 \(d_{i,j}\) 表示 \(i \sim j\) 的距离和。
题解:考虑对第一棵树进行点分,每次计算经过分治中心 \(x\) 的所有 \(Ad_{i,j}\) 产生的贡献。将 \(Ad_{i,j}\) 拆成 \(Ad_{i,x}\) 和 \(Ad_{j,x}\),每个可以分开独立算。固定一棵子树,以及子树里的一个点 \(u\),对于所有 \((u,v)\)(\(v\) 在子树外),要计算 \(B\) 树中 \(d_{u,v}\) 的和。为了方便,可以先计算所有 \(pair\) 的距离和,再容斥地减掉 \((u,v)\) 都在子树内部的方案数。
可以在 \(B\) 树上建出 \(A\) 的虚树,两遍 \(dp\) 求出距离和。也可以先构建一棵 \(B\) 的点分树,快速求一个点到一个点集的距离和。
常数较大,可以考虑一些优化。比如,容斥过程中,没必要直接在当前层减掉子树的方案(因为这样要在虚树或者点分树里重新插入子树里的所有点)。到了下一层,本来就会有插满整棵树的过程,我们可以到下一层时再减掉。
听说 \(claris\) 有 \(O(\log N)\) 做法。第一次学会了边分。可是还没领悟到他的做法。嘤嘤嘤……
day3
【B,E,H,J】
猥琐题。
【A√】
题意:有 \(N(\leq 10^6)\)根平行的轨道,共有 \(M(\leq 10^6)\) 横向的短棒支在一些相邻轨道上。当球从某根木棒下落时,一旦碰到短棒,就会滚到相邻轨道,并继续下落。给出初始时所有短棒的高度(保证互不相同)以及 \(Q(\leq 10^6)\) 个操作,每次删掉某根木棒,或询问从轨道 \(x\) 下落的球最终会落到哪个轨道。
题解:这个模型之前好像遇到过一次了……将木棒两段的点视作关键点,连同每根轨道初始的 \(N\) 个点。根据下落规律,在这些点之间连边,容易发现连成的是一条条链。更神奇的是,每当删掉某根木棒的时候,相当于将两条链在特定位置交换尾部。我们可以直接用 \(splay\) 来维护链,\(splay\) 的 \(key\) 就是链的深度。询问时直接查询最深的点即可。时间复杂度 \(O(N \log N)\)。
【C√】
题意:用 \(M(\leq 100)\) 个模式串 (\(|S| \leq 100\)) 消一个长度为 \(N(\leq 100)\) 的母串。每次消掉匹配上的位置,剩下的串前后接起来。问最少消几次能消光。
题解:以前做过一个模式串的题。设 \(g_{i,j}\) 表示消完 \(i \sim j\) 的最少步数,\(f_{i,j,k,l}\) 表示消 \(A_i \sim A_j\),消完后还剩下第 \(k\) 个串长度为 \(l\) 的前缀 的最少步数。转移时枚举后面消光的一段 \(g_{j+1,t}\),转移到 \(f_{i,t,k,l+1}\)。复杂度 \(O(N^5)\)。
【D√】
题意:总共有 \(N(\leq 8)\) 种牌,给出 \(N \times N\) 的大小关系矩阵。甲有 \(n_1\) 张牌,乙有 \(n_2\) 张牌,两人博弈,每次双方出一张牌。若牌有大小之分,小牌被丢弃;如果牌一样,都被丢弃。赢的人得 \(1\) 分,输的人不得分,平局各得 \(0.5\) 分。双方都想使自己分数高,问最终分数的期望。
题解:因为执最优策略,\(N\) 又比较小,肯定要子集 \(DP\)。现在问题是,给出目前甲乙的牌集(假设更小的集合我们已经 \(DP\) 过了),如何确定甲乙出牌规律。这个转移可以抽象为一个矩阵:甲选一行,乙选一列,甲想使数值最大,乙想使数值最小,求期望。
注意到这是双人有限零和博弈,是纳什均衡的基本模型。纳什均衡:没有玩家可以从单方面改变他或她的策略中获益。一个推论:如果乙的策略未知,甲采用某种纳什均衡混合策略,能使可能的最大损失最小。相关资料
由这个推论,设 \(p_i\) 表示甲对于每一行选的概率,我们可以直接得到矩阵模型里期望值 \(w\) 的线性规划方程。
一个有趣的事情:如果我们根据乙来列方程,显然最终求得的 \(w\) 是一样的,而新方程正好是原方程的对偶式:侧面映证了线性规划对偶转化的正确性。
单纯形来解有种大材小用的感觉?事实上,如果满足 \(p_i >0,q_j>0\),可以直接用高斯消元解出甲的策略 \(p_i\)(乙也同理)。
为什么在保证 \(>0\) 的情况下,\(\geq w\) 就能变成 \(=w\) 了呢?感性地想一下,每一个 \(p_i\) 都 \(>0\),如果有一个 \(\sum\) 偏大,我总能通过加加减减 \(p_i\),使 \(w\) 偏大。但是如果某个 \(p_i=0\) 了,继续往下减是不符合限制的。
在一般情况下,\(p_i\) 和 \(q_j\) 有可能是 \(0\)。所以我们要枚举它们的一个非零的集合,才可以用高斯消元解出它们(我们总能证明,一定存在一种纳什均衡,使得不为 \(0\) 的行和列一样多,这样就可以安心消啦)。每解出一组解,记得带回去检查:所有 \(q_j=0\) 的 \(j\),\(\sum p_i a_{i,j}\) 不能超过 \(q_j >0\)。
【F√】
题意:给出一个长方形的三条边 \(a,b,c\)。要从一个顶点出发,走到面上的任意一个点,问最短距离最大能是多少。
题解:开场 \(WA\) 了一片……首先,最远的点并不是对角的那个顶点。如果我们要从 \((0,0,0)\) 走到面上的一个点 \((x,y,z)\),分类讨论一下是有四种可能的路径(其中有两条必然存在,有两条两者可能不存在),最短距离是它们的 \(min\)。因为是求 \(min\) 的最大值,可能从对角的顶点往边上挪一挪,会使原最来的 \(min\) 变大一些,使得答案变优。我最后暴力列出这个求 \(min\) 的式子,无脑写了一个模拟退火。
【G√】
题意:数轴上有 \(N(\leq 5000)\) 个点 \(a_i\)。设置 \(K(\leq 5000)\) 个 \(b_i\),使得 \(\sum \min_{1 \leq j \leq K} |a_i-b_j|\) 最小。
题解:其实肯定是按顺序划过去,每次放置在一个集合的中位数上。比赛时用 \(O(N \log N \log V)\) 的 \(zyb\) 二分卡过去的。二分新增集合的代价 \(C\) 后,\(f_i=\min(f_j+cost(j+1,i)+C)\)。这个东西有决策单调性,所以采用二分和栈来维护。
类似 \(f_{i,j}\) 表示前 \(i\) 个点,选了 \(j\) 个集合 这种 \(DP\) 模型也存在一种四边形不等式的优化。脑补一下就有 \(opt_{i-1,j} \leq opt_{i,j} \leq opt_{i,j+1}\)。按 \(i\) 升序 \(j\) 降序的顺序做即可。复杂度 \(O(NK)\)。
【I√】
题意:考虑模质数 \(p\) 域下的多项式 \(f(x)=x^n+a_{n-1}x^{n-1}+\dots+a_1x+a_0\) 构成的集合 \(Z_n\)。问有多少个元素是不可约的,即不存在一个多项式 \(g \in Z_k\),使得 \(f\) 模 \(g\) 为 \(0\)。答案对 \(m\) 取模。\(m,p,n \leq 10^9\)。
题解:有重要性质:\(x^{p^n} -x=\prod Q(x)\),其中 \(Q(x)\) 是所有集合 \(Z_k\) 满足 \(k|N\) 的并。所以直接套莫比乌斯反演即可。
day4
【A√,E√,B,C】
水题;猥琐题。
【D√】
题意:有 \(N(\leq 10^5)\) 个人,每个人头上会有一顶非黑即白的帽子。再给出 \(M\) 组有向关系 \((u,v)\),表示 \(u\) 能看到 \(v\) 头上的帽子。问是否存在一种猜自己头上帽子的策略,不管帽子颜色如何分配,至少有一个人能猜到自己头上帽子的颜色。
题解:一个人猜自己帽子的策略无非是 \(f_i(p_{i,1},p_{i,2} \dots)\),\(p_{i,j}\) 是它看到的帽子颜色。
如果图中存在至少一个环,必然有解。比如三元环,颜色分别是 \(a,b,c\)。第一个人可以猜自己是 \(b\),第二个人猜自己是 \(c\)。如果要让它们都猜错,则 必须满足 \(a=b=c\)。这时候第三个人猜自己是 \(~a\),则不存在一组全猜错的分配方案。
如果图中没环,你总能以拓扑序的方式去分配帽子颜色,使得所有人都猜错。
【F√】
题意:定义一个长度为 \(k\) 的串 \(S\) 的回文度是满足 \(0 \leq i < k-i-1\) 且 \(S_i=S_{k-1-i}\) 的 \(i\) 的个数。给出一个长度为 \(N(\leq 123456)\) 的串,求其所有子序列的回文度之和。
题解:直接枚举两个位置 \((i,j) S_i=S_j\),计算它们出现的次数。它们中间的串不造成任何影响,所以方案是 $\sum \limits_k \binom{i-1}{k} \binom{n-j}{k} $。将右边的组合数写成 \(\binom{n-j}{n-j-k}\),这个求和式直接等于 \(\binom{i-1+n-j}{n-j}\)。现在变成了卷积式,直接对于每一种字符 \(NTT\) 即可。
【G√】
题意:维护一个 \(N(\leq 10^6)\) 个数的数组和 \(Q(\leq 10^6)\) 个操作:① 将第 \(x\) 个数换成 \(y\);② 给出一个区间 \((l,r)\) 和一个常数 \(k\),且 \(k,k+1,\dots,k+m\) 是这个区间的子序列,问 \(m\) 最大能是多少。
题解:一个很直接的想法是,对于每一个数 \(a_i\),记录下一个值为 \(a_i+1\) 的数组下标。这样可以用 \(LCT\) 来维护这些森林。但是每次修改数字的时候,涉及到的点可能会很多。
在原来的基础上改进一下:维护每一个数 \(a_i\) 后面第一个出现的 \(a_i\) 或 \(a_i+1\)。为了方便维护答案,可以把后者的点权设为 \(1\),询问时求个和即可。这样修改时只涉及 \(O(1)\) 个数了。