由于一些…我也不知道是什么原因吧,似乎 UOJ 现在干活的管理员只剩我和 AwD 了o(╥﹏╥)o,这次正好过年离 WC 比较近,我到家的时候离过年也没几天了,比赛这么鸽还是要道歉 = =
感谢本次救 UOJ 于题不全办不出比赛之中的各位出题人 laofu, matthew99, zhouyuyang, WuHongxun, Picks!
特别感谢将 E 题从 WC 的课件中移到 UOJ 的比赛中的 Picks 老师,牺牲了 WC 第一课堂上大家冬眠的时间,换来了一个超有趣的 E 题!
同时感谢 AwD 一天写出约 1 sdn (1 sdn = 11.7KB, 关于这一单位的来源见【集训队作业2018】蜀道难) 代码的精彩表演!
接下来是这场比赛的题解,这次的 A 题比往常的 Goodbye Round 的 A 题更难一点,这是因为 ABC 三个题都觉得挺好的有点舍不得扔,在 A 前面再加一个题又和传统不太符合。一直担心大家 A 题会出现惨案,不过从比赛中大家通过了 40 人并且大多数人都拿到了可观的分数(>0)这一点来看还是比较成功的!
新年的拯救计划
最早AC: ridiculos (0:14:21)
算法一
手玩
算法二
直接套用求最多边不相交生成树的方法(见李煜东“图连通性若干问题探讨.pptx”),时间复杂度
算法三
显然我们会发现构造出的树的数量不超过
咦这个 A 题怎么这么难?咦怎么有个 Subtask 部分分这么多?肯定是用来平衡题目难度造成的平均分下降的,总之就是这个部分分肯定很水!
容易发现,当
期望得分 44 分,结合之前的算法可以获得更高分数。
算法四
我们尝试构造一种恰好为
如何构造
考虑提出那条长为
当
当然本题的构造方法有多种,一些不同的方法也可以通过 = =
新年的Dog划分
from matthew99, 标程和数据 by matthew99, 题解 by whzzt
最早AC: peehs_moorhsum (1:23:44)
算法一
注意到图是二分图时,若我们将图划分成两个非空部分
考虑返回值为联通的情况。不妨假设最终二分图两侧的点集分别为
因此当图是二分图时,我们只要枚举点集进行询问即可。
询问次数
算法二
为了获得最终二分图的两部分,我们尝试获得原图的一棵生成树。
我们可以考虑尝试删掉二分图中所有的边,如果一条可能的边删除后连通性发生了改变,我们就保留这条边,否则删去这条边。最终图中一定会剩下恰好
于是我们只要将生成树黑白染色就可以得到二分图的一个部分了。
询问次数
算法三
刚刚的寻找生成树的方法实在是太暴力了,我们可以对刚刚的方法进行一些优化:二分查找下一次保留边会发生在什么时候。由于这样的事件只会发生
注意到我们找到了原图的一个生成树,只靠这个生成树是可以让原图联通的。那么我们可以保留生成树上的边,删去其它连接二分图两侧的边。如果图不是二分图,那么图中一定存在环,于是一定存在剩余的某条树边删去后仍然连通。
每次二分需要
算法四
为了去掉 2 的常数,我们需要将对边二分优化为对点二分。
考虑从 1 号点开始,使用 BFS 进行上述过程,就只要对点二分了。
询问次数
新年的小黄鸭
from zhouyuyang, 标程、数据和题解 by zhouyuyang
最早AC: supy (3:06:13)
算法负二
大胆猜想直接树剖答案最优。
获得
算法负一
大胆猜想在子树size过大的时候可以钦定重儿子。
获得
算法零
大胆猜想在子树深度和过大的时候可以钦定重儿子。
获得
算法一
直接暴力枚举哪些是重边。
时间复杂度
算法二
假设我们已经知道了你的轻重边划分方案
显然如果一条边是轻边我们直接把它扔进
如果遇到了轻边,那么在这个轻边父亲节点向上的重链长度显然不会改变,也可以扔进
设
转移直接枚举重儿子,并且更新当前状态。
时间复杂度
空间复杂度
算法三
观察DP状态,我们发现我们可以使用某些技巧干掉
我们考虑在产生
这样子直接设
转移仍然直接枚举重儿子。
时间复杂度
空间复杂度
算法四
继续观察DP状态,我们发现我们可以尝试只存下来
转移我们枚举在
观察算法三中的DP转移方程,不难发现在钦定重儿子的时候转移方程形如
因为在转移的重链上的点
此时转移方程就可以看成路径点权和加上
对于叶节点的情况,我们可以维护
对于非叶节点的情况,不难发现合法转移只有
非叶节点的点权和可以在确定
时间复杂度
空间复杂度
算法五
出题人卡内存怎么办???
考虑通过一些操作把
此时我们每个点的点权就唯一了,线段树就只需要一颗了。
其于基本同算法四。
时间复杂度
空间复杂度
算法六
from: matthew99
算法四,五我听不懂怎么办?
考虑对于每一个节点x维护一个分段函数表示
我们可以发现分段函数的段数的上界是
直接启发式合并维护即可。
时间复杂度
空间复杂度
算法七
from: matthew99
在审题的时候@whzzt说分段函数段数
此时在算法六的基础上套长链剖分,暴力合并,时间复杂度可以做到
但是因为出题人 zhouyuyang和审题人whzzt太咕咕咕了,没有实现过这个算法,也没有想过算法细节。
时间复杂度
空间复杂度
新年的族谱树
from WuHongXun, 标程和题解 by AwD, 数据 by whzzt
whzzt: (;´д`)ゞ因为懒得写 spj 加了个权值,为了让问题描述看起来更合理一点加了一大堆废话= = 似乎大家没怎么看懂的样子
算法一
枚举族谱树所有的形态,找一个字典序最大的输出来。
时间复杂度不明。
算法二
怎样的老家族集合是合法的?
最终选择的集合确定了一棵有根树,选出的集合作为有根树的子树,两两之间要么是包含的,要么是分离的。
要求字典序最大的方案,也就是要尽量选择权值大的老家族的集合。
按照套路,显然可以得到一个简单的贪心:沿权值降序依次考虑每个集合,若它与之前选择的集合没有冲突,则选择该集合。
一共有
使用 bitset 可以将判断合法性的复杂度优化至
时间复杂度为
算法三
在后文中,我们将会把一类有根树称作族谱树 —— 族谱树的叶子节点都是元素,非叶节点都是一个包含了其子树中的元素的集合,每个非叶节点至少有两个孩子。
由于族谱树它真的是一棵树,因此并不用依次检测当前集合
于是就可以提高判断合法性的效率了:
首先,找到包含
对于
于是就可以在
当合法的时候,大力重建族谱树。
时间复杂度为
算法四
在上一个算法中,第一步的时间复杂度可以做到
在静态的树上维护动态的树是很困难的,不妨在动态的树上维护静态的树。
不失一般性的假设
具体来说,对于每个族谱树中的集合
于是检测一个集合是否合法的复杂度就降到了
瓶颈成了每次修改族谱树,理论上应该能做到
时间复杂度为
算法五
考虑修改族谱树的过程 —— 我们只是增加了一个节点,并将该节点父节点的一些孩子移动给了它。这个操作在第
平衡树启发式合并
这个东西实现出来就是
插入节点的时候需要知道集合的 LCA 的序号,因此在 toptree 上还需要维护一个子树的 LCA。当然,这里并不需要强上一个
时间复杂度为
为什么
新年的A+C Problem
from Picks, 标程和数据 by whzzt, 题解 by Picks
本题中的模型其实是来源于量子计算的模型。题中可使用的门是三元可逆逻辑门,而在真实的量子计算中是Hilbert空间中的线性变换,其中可逆逻辑门可以在量子计算中实现。
题目的任务是求对于长度为l的输入整数a进行加常数c的可逆电路,其中可利用的资源有三类额外位:
- 泄露位:初始为0,输出可以为任意值的位。由于可逆运算中信息是守恒的,当输出为任意值时,输入的信息会泄露到这些额外位中。当有人获取了额外位的输出,是可能获得额外位的信息的。
- 干净位:初始为0,输出时也为0的位。这些位可以视为一个资源池,从中取出时是0,放回时也是0。
- 脏位:初始时不知,输出时需要还原为初始状态的位。这些位可以从系统的任意无关位置取出,在过程中利用完之后放回原位。
显然这三类额外位存在支配关系,泄露位的利用严格容易于干净位,干净位的利用严格容易于脏位。
子任务一、二
有许多泄露位可以利用时,有很多种做法都可以解决这个问题。
最简单的方法是从低到高枚举每一位,用一位存下当前的进位。但由于
根据实现的不同需要 l 左右个泄露位。
子任务三
当我们有
注意到我们无法绕开进位,我们不妨使用
同时,当我们用
即如下过程:
fixpoint adder(a[i], b[i], q) :=
MAJORITY(a[i], b[i], q);
adder(a[i+1], b[i + 1], q);
reverse(MAJORITY)(a[i], b[i], q);
TRIXOR(a[i], b[i], q).
回到问题,我们一开始将常数
子任务四
此时我们只有
在上一个子任务中,我们发现最关键的问题即是进位问题,我们考虑如何比较好地解决进位问题。注意到
子任务五
该子任务中我们仅有
这时我们需要利用一个补码的性质:在模
我们利用一个技巧来处理加
粗略观察,此时我们使用了
子任务六
现在我们仅有一个额外位了。我们先考虑一些可能的子任务。
你需要对利用计算过程
的一位结果 来控制一个对 变量的操作 ,其中 ,但除 外你仅有 个额外脏位 。
我们可以构造如下过程:
Definition dirtyControl(P, O, A, B, q) :=
controlled(O)(q, B);
P(A, q);
controlled(O)(q, B);
reverse(P)(A, q).
注意到当
当你有
个额外脏位,还有一个输入位 存有 或者 ,你需要计算 。
这个与子任务五非常相似。我们提供两种方法来完成。
一种是非常粗暴的方法,即使用
另一种是灵巧一点的方法,我们考虑子任务五中
当你有
个额外脏位 ,你要获得 的最高进位,输出在干净位 中。
还是利用小问题1中的方法,我们用第
Fixpoint dirtyAdd(a[i], c[i], q[i]) :=
If c[i]=1 then ( (controlled(NOT)(a[i], q[i])); NOT a[i]. )
controlled(controlled(NOT))(q[i-1], a[i], q[i]);
dirtyAdd(a[i-1], c[i-1], q[i-1]);
controlled(controlled(NOT))(q[i-1], a[i], q[i]);
即当更低位的脏位不变时,该位进位由
现在我们利用一个额外干净位
我们先利用小问题3,视
子任务七
此时额外位是一个脏位g。我们再次利用小问题1中的方法来解决这个问题。 最终的方法为:
Fixpoint addC(a, g) :=
Let p, q as described;
P2(g, q, p);
controlled(allNOT)(g, q);
P3(g, p, q);
P2(g, q, p);
P3(g, p, q);
controlled(allNOT)(g, q);
addC(p, g);
addC(q, g);
扩展
如果我们不局限于三元逻辑门,而是可以使用量子门,则额外的一个脏位也是可以省去的。参见参考资料【3】。
参考资料
- Craig Gidney. Constructing Large Increment Gates. http://algassert.com/circuits/2015/06/12/Constructing-Large-Increment-Gates.html
- Thomas Häner, Martin Roetteler, Krysta M. Svore. Factoring using 2n+2 qubits with Toffoli based modular multiplication.
- Craig Gidney. Trouble Adding Constants into Qubit Registers. http://algassert.com/post/1701