CTT 结束后发现自己胡策题都没咋补,这下尴尬了。主要原本胡策就打着玩的(
怎么 CTT 平均难度比胡策还要简单啊.jpg。
还是随便写几篇题解吧。
先来个补全进度表,根据胡策 OJ 或 qoj 通过情况来评判:
Problem List
- 测试赛(10.22)
- Day 1(10.23)
- Day 2(10.29)
- Day 3(11.04)
- Day 4(11.05)
- Day 5(11.07)
- Day 6(11.09)
- Day 7(11.11)
- Day 8(11.12)
- Day 9(11.14)
- Day 10(11.16)
- Day 11(11.19)
- Day 12(11.21)
- Day 13(11.23)
- Day 14(11.25)
- Day 15(11.26)
- Day 16(11.28)
- Day 17(11.30)
题解会补的,你先别急。
待更新题解:
- Day 1 优惠购物
- Day 7 重排
- Day 10 雷同
- Day 12 这不是一道数据结构题
- Day 16 积性函数
Day 7 意念力
题解
考虑链的情况。
容易想到容斥,变成共有 m 种颜色然后给某个节点染色。
我们按链的顺序依次染,每个节点和前若干个不相同,且前若干个也互不相同,容易发现就是形如 ∏(m−aj),可以直接多点求值或者点值平移。
对于树的情况,我们考虑如何变成和链一样的问题。
结论:我们按照深度顺序加点即可保证与链的情况一致,使得距离小于 k 的点满足。
证明是容易的。
写个震波的点分治即可。
总复杂度 O(nlog2n),可以通过。
Day 9 最短路求和
题解
称 c=m−n。
考虑先不断把所有一度点缩到其余点上直到不存在一度点,并同时计算贡献。
c=−1 时已经做完了。
那么剩下的图中度数 ≥3 度点个数不会超过 2c 个。
找出这些点并称为关键点,c=0 时任意钦定一个点当关键点。
接下来剩下的二度点缩成若干条关键点之间边。
显然最后变成的图中的边数(包括重边、自环)在 c>0 时不会多于 3c 条。
考虑计算贡献。
首先 O(c2logc) 求出新图全源最短路。
然后关键点之间的答案立刻求得。
非关键点和关键点之间的答案可以通过枚举非关键点旁边的关键点来统计。
对于非关键点之间分类讨论。
单条缩完后的边内部就是一个双指针即可。
对两条这样的边之间的贡献,考虑第一条边内的点到第二条边的两侧的路径方案,是从自己的哪个关键点方向走的,显然可以分 4 类讨论贡献。
对于同一类贡献的点,要么第二条边内的点走的左右方案是确定的,要么可以双指针直接维护。
这样的复杂度容易发现即为 O(nc) 的,最后总复杂度 O(c2logc+nc)。
实际上由于数据很水所以直接暴力枚举非关键点对就可以通过了。
Day 9 Tree Topological Order Counting
题解
感觉做法和正解很不一样(哪有正解做这么麻烦的?),记录一下。
首先我们容易知道一颗树的拓扑序总数是 n!/∏jsizj 的,比较简单的证明方法是直接删根然后归纳。
然后我们考虑计算每个节点的答案。
我们枚举过去,假设当前枚举到节点 p,设其到根的链上的节点从上到下依次是 p1,p2,p3,…,pm,pm+1,其中 pm+1=p。
对于 pk 除了 pk+1 外的子树,内部的枚举顺序是容易计算的,我们不妨先忽略之,最后记得再乘上就可以了。我们只用知道 pk 除了 pk+1 外的子树有恰好 sizpk−sizpk+1−1 个节点并且已经按某种拓扑序排好了即可。
考虑用 EGF 刻画拓扑序上比节点 p 小的元素,并设 ak=sizpk−sizpk+1,那么显然恰有 k 个元素比当前点拓扑序小的方案数为
[tkk!(n−k−1)!]1(am+1−1)!∫(∑jtjj!(a1−j−1)!)∫(∑jtjj!(a2−j−1)!)…∫(∑jtjj!(am−j−1)!)dt…dtdt
(实际上是二元 GF,另一维刻画拓扑序上比当前节点大的节点数目,不过由于两元总和在最后的柿子里始终是 n−1 所以第二元直接被省略了)
其中每个积分表示加根,并且常数项为 0。
我们考虑到这个柿子实在太丑,我们不妨分别乘上一个 (ak−1)! 再除掉,那么就变成 (1+t)ak−1/(ak−1)!,而众所周知我们计算子树贡献时的柿子就是最开始所提到的,因此可以刚好消掉那个 n! 并且体现了对不同子树分配标号,记得对每个子树预处理下 1/∏j∈Tsizj 即可。
现在我们要求出
wp=∑kbk+1k!(n−k−1)![tk]∫(1+t)a1−1∫(1+t)a2−1…∫(1+t)am−1dt…dtdt
由于这里的积分要求常数项为 0(或者说是一种类似定积分的形式),我们发现此处应有
∫(1+t)am−1dt=(1+t)am−1am
于是提出常数,拆开 −1,我们发现就变成了
wp=1am∑kbk+1k!(n−k−1)![tk]∫(1+t)a1−1∫(1+t)a2−1…∫(1+t)am+am−1−1dt…dtdt−1am∑kbk+1k!(n−k−1)![tk]∫(1+t)a1−1∫(1+t)a2−1…∫(1+t)am−1−1dt…dtdt
我们发现后半部分柿子就是 wpm/am!
继续保持展开直到不能展开,我们就得到了
wp=1∏mk=1(sizpk−sizp)∑kbk+1k!(n−k−1)!(n−sizpk)−∑iwpi∏mk=i(sizpk−sizp)
预处理下逆元,然后就可以做到单次转移 O(n) 的 dp 了。记得所有结束后还要把其余子树的枚举方案数统计进答案。
总复杂度时间 O(n2),空间 O(n)。
值得注意的是,预计本题正解中这个 −1 可能会被组合意义解释成某种容斥的形式,从而转化成直接的 dp,而无需生成函数推导。
不出意外的话,使用树分块 + MTT 大概可以做到 O(n√nlogn) 左右的复杂度,不过肯定没人会去这么干。
点分治 MTT 不知道能不能做,如果能的话大概可以做到 O(nlog3n) 左右?
Day 10 茧
题解
考虑依次解决 k=1,2,3,4,5。
k=1 就是 nim 游戏,不多说了。
考虑对 k=2 的 SG 值找规律。
仔细看发现每相邻两个 0 之间均为一段排列,如开头一段
| 0 1 0 1 2 0 1 2 0 3 1 2 0 3 1 2 4 0 3 1 2 4 0 3 1 5 2 4 0 3 1 5 2 4 0 3 6 1 5 2 4 0 3 6 1 5 2 4 0 7 3 6 1 5 2 4 0 7 3 6 1 5 2 4 8 0 7 3 6 1 5 2 4 8 0 7 3 6 1 5 2 9 4 8 0 7 3 6 1 5 2 9 4 8 |
并且后面有一段形如
| 15 |
| 7 |
| 29 |
| 14 |
| 28 |
| 3 |
| 27 |
| 13 |
| 26 |
| 6 |
| 25 |
| 12 |
| 24 |
| 1 |
| 23 |
| 11 |
| 22 |
| 5 |
| 21 |
| 10 |
| 20 |
| 2 |
| 19 |
| 9 |
| 18 |
| 4 |
| 17 |
| 8 |
| 16 |
规律很明显了:设 P0=<0>,P1=<1,0>,P2=<1,2,0>,P3=<3,1,2,0>,…,那么此时 SG 序列总形如
P0,P1,P2,P2,P3,P4,P4,P5,P5,P6,P6,P7,P8,P8,…
即只有 j=2k−1 的 Pj 会只出现一次,否则总是出现 2 次。
且总有:
- Pi−1 是 Pi 删去 i 的结果
- P2n−1,j={P2n−1−1,j/22∣j2n−j+122∤j=2n/lowbit(j)−j/lowbit(j)+12
这部分证明可以使用归纳法,但是详细的证明并没有什么意义。
容易在 O(logv) 内快速算出 SG 值从前缀异或。
接下来考虑 k=3。
打表发现规律类似,只是 Pj=<0,1,…,j>,且每段的出现次数有了改动:Pj 会出现恰好 3j 次。也即
P1×3,P2×6,P3×9,P4×12,P5×15,…
经过一定的讨论和枚举,这也是容易解决的,接下来看 k=4。
观察发现此时单段 Pj 与 k=2 相同,且 SG 值出现规律为
P0,P1×7,P2×22,P3×43,P4×74,P5×112,P6×158,P7×211,P8×274,…
容易发现为 Pj×(4j2+2j+2−[j+1=lowbit(j+1)])。
k=5 时的单段排列与 k=3 时类似,而排布规律为
P1×15,P2×70,P3×195,P4×420,P5×775,P6×1290,P7×1995,…
也即 Pj×(5j3+5j2+5j)。
至此 k=3,4,5 的规律都被找出了。
由于这样的段数显然分别是 O(k√v) 的,直接枚举出所有这样的段,每次查询时直接二分所在段然后计算贡献即可。
不过考虑怎么写会好写一点:考虑单写 k=1,然后把 k=2/4 一起解决,k=3/5 一起解决。
k=1 时就是求 0⊕1⊕2⊕⋯⊕a,这部分容易利用 4|a+1 时值为 0 来解决。
k=2/3/4/5 时,考虑每个 Pj 前有多少元素:
- k=2 时为 j2+j−∑2t≤j2t。
- k=3 时为 j3−j。
- k=4 时为 j4+j−∑2t≤j2t。
- k=5 时为 j5−j。
这也恰是归纳法中所要证明的关键。
这样我们就可以在 O(logv) 时间内快速二分出当前询问的 a 在哪段 j 内。
对 t<j 部分 Pt 的贡献,k=2/4 时为 [j>1],k=3/5 时为 [jmod8∈{2,3,4,5}]。
对于当前 Pj 的贡献,假设已经有 t 个整段,那么整段的总贡献即为 [2∤t](0⊕1⊕2⊕⋯⊕j),其中这段前缀异或就是 k=1 的情况。
对于当前段,假设有 b 个元素,k=3/5 时和 k=1 一样,k=2/4 时直接使用之前的递归式即可。
事实上,可以想到对于更大的 k,也可以奇偶讨论得到类似 k=2/3 的结论。
总复杂度 O(nlogv),其中认为 k 为常数。
Day 12 goods
题解
通过简单的 FWT 转化,容易发现本题的关键是对 0≤a≤n 求出
∑j(2jB)[zj](1+z)a(1−z)n−a
也即
∑j(jB)[z2n−j](z2+1)a(z2−1)n−a
也即
[z2n]zB(z2+1)a(z2−1)n−a(1−z)B+1=[z2n−B](z2−1)n(1−z)B+1(2z2z2−1−1)a=(−1)a∑j(aj)2j[z2n−B](z2−1)n(1−z)B+1(z√1−z2)2j
于是考察(其中 c=2n−B)
[zc](z2−1)n(1−z)B+1(z√1−z2)j
注意到
(z√1−z2)⟨−1⟩=z√1+z2
于是使用另类拉反,就有
[zc](z2−1)n(1−z)B+1(z√1−z2)j=[zc]((z√1+z2)2−1)n(1−(z√1+z2))B+1zj(z√1+z2)′(zz√1+z2)c+1=(−1)n[zc−j](√1+z2+z)B+1√1+z2
该部分容易做到线性。
最后总复杂度 O(nlogn),瓶颈在于中间的一次卷积。
Day 15 染色
题解
容易想到 FWT。
一个 a 位为 1 的位置的 GF 为 [2∤a]za。
FWT 后,一个 a 位为 1 的位置的 GF 为
∑i∑j[2∤i+j](ai)(m−aj)(−1)izi+j=(∑i∑j(ai)(m−aj)(−1)jzi+j−∑i∑j(ai)(m−aj)(−1)izi+j)/2=(1+z)a(1−z)m−a−(1−z)a(1+z)m−a2
于是答案即
12m[zk]∑j(−1)m−j(mj)((1+z)j(1−z)m−j−(1−z)j(1+z)m−j2)n=12n+m∑j(−1)m−j(mj)∑t(−1)t(nt)[zk](1+z)(m−j)t+j(n−t)(1−z)jt+(m−tj)(n−t)
核心就变成了对 j=0,1,…,nm 求出 [zk](1+z)j(1−z)nm−j。显然有
[zk](1+z)j(1−z)nm−j=∑t(−1)t(nm−jt)(jk−t)=(nm−j)!j!∑t1(nm−j−t)!(j+t−k)!(−1)tt!(k−t)!
一遍差卷积即可。
总复杂度 O(nmlog(nm))。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
2022-12-09 八校杭州集训练习记录