模拟赛杂题
模拟赛杂题
18th D
我认为较长时间应当可以独立完成。比较综合的计数题。
考虑一个简化的问题,如何计数一个序列的本质不同子序列。
考虑模拟子序列匹配的过程,每一位字符都找到最近的可以匹配的进行匹配
这告诉我们,如果对于两个字符 \(i,j\),\(a_i=a_j\),且 \([i+1,j-1]\) 之间没有任何字符,那么选取 \(i\) 与选取 \(j\) 是等价的。
可以考虑一个 \(dp\),设 \(f_{i}\) 为当前最后一个字符匹配到了 \(i\) 的本质不同子序列个数。
则设 \(p\) 为 \([1,i-1]\) 里 \(a_p=a_i\) 的最大 \(p\),如果不存在则为零,则 \(f_i=\sum_{j=p}^{i-1}f_j\),\(f_0=1\)
可以 \(O(n)\) 做。
那么扩展到这里,我们考虑每个元素的消失时间 \(t\),也相当于是 \(a_i=a_j\),则在这俩元素首次消失一个的时候,这时候两元素中间如果没有存在的元素,则必会导致重复。
也就是必须有 \(\max_{x\in [i+1,j-1]} t_{x}> \min(t_i,t_j)\),如果两个都要保留。
那么还有中间这时候已经删空,那么我们保留其中一个,让它继续存活,不妨钦定保留靠后的一个,也就是钦定 \(t_i\ge t_j\) 吧。
所以我们需要要求存在 \(k\) 的时刻就有 \(t_i<t_j\)。
转化一下描述,就是:
\(\forall i<j,a_i=a_j,t_i<t_j,\exists k,i<k<j,a_k\neq a_i,t_k>t_i\)
这东西保证了子序列匹配过程中的唯一解,所以是充分的(很直觉显然)
继续转化为一个更简洁的描述,方便计数,就有:
\(\forall i\),设 \(k\) 是其后面第一个大于 \(i\) 的元素,则必须有 \(t_k\neq t_i\)
考虑直接区间 dp,设 \(f_{l,r,x}\) 为区间 \(l,r\),最大值为 \(x\),且 \(t_{r+1}>x\) 的方案数,为了便于记录不妨令 \(a_{m+1}=0,t_{m+1}=n+1\)
至于对于多个取到最值的点,我们钦定为最小的一个进行划分(\(r+1\) 对所有的取到最值的点都提出限制)
那么就有:
可以通过前缀和优化到 \(O(nm^3)\)。
考虑到本质不同的 \(t\) 至多有 \(m+1\) 个,我们不妨设 \(g_i\) 为至多使用 \(i\) 个不同的 \(t\) 的方案数,这显然与 \(\sum_{j=1}^i f_{1,m,j}\) 等价(因为我们保证了最大值是取到了的)
再设 \(f_i\) 为恰好用 \(i\) 个不同的 \(t\) 的方案数,可以被 \(g\) 二项式反演出来。
则答案就是 \(\sum f_i{n\choose i}\)
19th D
同 P4352
感觉很自然的,主要是场上没看这题
首先在足够多次正着和反着操作后所有值会变成一样,每次操作不会增大相邻两个元素的高度差,合并的时刻至多 \(n\) 个,我们考虑加速这个过程。
首先合并相同值,然后就可以通过判断左右侧的值判断左侧操作/右侧操作当前段是否会增高,不妨设这个为 \(g_{i,0/1}\)
然后考虑第 \(i\) 段与第 \(i-1\) 段的相对变化,设 \(a=[g_{i,0}\neq g_{i-1,0}],b=[g_{i,1}\neq g_{i-1,1}]\),则经过 \(x\) 轮左侧操作和 \(y\) 轮右侧操作后其高度差缩小为 \(ax+by\),合并时刻就是找到 \(ax+by=\Delta h\) 的第一个时刻。
我们将这个时刻存入优先队列,取出时间最小的时刻,合并两个段,并且重构两侧关系(\(g\) 可以直接 \(0\) 取左侧的,\(1\) 取右侧的)。支持优先队列延迟删除就好了。
至于 \(ax+by\) 只有 \(x,y,x+y\) 两种可能,同时我们需要解决的是在时刻 \(t\) 之后的最近时刻,可以列出式子,最后就是对 \(x,y,x+y\) 其中之一的限制条件,可以通过桶来解决。
同时由于最大有效时刻不超过 \(m\),所以可以开 \(m\) 个 queue
替代优先队列,时间复杂度就线性了(使用链表的话)
这个题实现细节比较多
21th D
这一周唯一在考场想到正解的D,这里的想到指的是完整思路,虽然并没有写
首先考虑更项减损数,那么就会有 $\gcd $ 只与小数部分有关,因此可以先将 \(a\) 对 \(b\) 取模(如果为零取 \(b\),这方便处理边界)。
考虑对于每个质因子的贡献,设当前统计质因子 \(p\),\(c(x)\) 为质因子分解后 \(p\) 的指数
前面那个可以 \(O(nw(V))\) 计算,其中 \(w(V)\) 是最多质因子个数,在 \(V=10^6\) 时取 \(7\)。
问题化为高速计算
不妨按照 \(c(b_x)\) 排序(以后的 \(x< y\) 默认为 \(c(b_x)\le c(b_y)\))
-
处理 \(\min(c(b_x),c(b_y))\ge 1\)
\[\sum_{t=1}^{\lfloor\log_pV\rfloor}\sum_{x}\sum_{y<x,c(b_y)+c(b_x)\ge t}[a_xb_y\equiv a_yb_x(\bmod p^t)] \]我们令 \(g_x=c(b_x)\),令 \(h_x=\frac{b_x}{p^{g_x}}\),这样 \(h_x\) 与 \(p^t\) 就互质了,相当于求。
\[\sum_{t=1}^{\lfloor\log_pV\rfloor}\sum_{x}\sum_{y<x,c(b_y)+c(b_x)\ge t}[a_xp^{g_y}(h_x)^{-1}\equiv p^{g_x}a_y(h_y)^{-1}(\bmod p^t)] \]由于 \(g_y\le g_x\),分讨有:
-
\(t\le g_y\),这时候左右两侧都是零,可以直接算
-
\(g_y<t\le g_x\),这时候右侧是零,需要让左侧取到零,可以枚举 \(g_y\),另一半可以直接计算这样的数字个数
-
\(g_x<t\),这时候原式可以等效为
\([a_x(h_x)^{-1}\equiv p^{g_x-g_y}a_y(h_y)^{-1}(\bmod p^{t-g_y})]\)
我们只需要对于每个 \(y\) 枚举 \(g_x\),开桶加入贡献,然后对于每个 \(x\) 枚举 \(g_y\) 计算贡献即可。
-
-
\(\min(c(b_x),c(b_y))=0\),则 \([a_xb_y\equiv a_yb_x(\bmod p^t)]\),显然由于 \(\gcd(b_y,p^t)=1\),则将 \(b_x\) 写为 \(h_x·p^{g_x}\) 又有:
\([a_x(h_x)^{-1}\equiv a_y(b_y)^{-1}p^{g_x}(\bmod p^t)]\)
由于 \(g_x+g_y\ge t,g_y=0\implies g_x\ge t\) 所以右侧为零,因此只需要判断左侧是否为零即可。
至此本题完结。
复杂度应当是 \(O(V\log\log V+n\frac{\sqrt V}{\ln V}+nw(V)\log^2 V)\)
前面是预处理复杂度。独立补题时常 大概100min
若痕迹都不曾亲眼见过
若连平凡都显得像个传说
还留什么时间惋惜惶惑
——《夏虫》
22th C
定义 \(w(i,j)=a_i\oplus j\),表示按位异或,求所有序列 \(a,a_i\in [0,2^m-1]\cap \mathbb{Z}\) 的最小异或生成树边权和。
同 BZOJ4770
考虑 Boruvka 在 Trie 上的体现,其实就是一个逆序过程。如果 Trie 上一个节点 \(x\) 左右儿子都有点,那么在左右儿子各取一个点出来找到的最小边权一定在最小生成树里面,这是明显的。
所以我们考虑设一个 \(dp\) 表示 \(dp_{n,m}\) 为节点数为 \(n\),层数为 \(m\) 的答案(对应二进制下从第零位开始的第 \(m-1\) 位),我们需要一个 \(F(x,y,h)\) 为左子树有 \(x\) 个点,右子树有 \(y\) 个点,这一条最小边权的权值乘以方案数之和是多少(不算当前这一层的话)。
那么就会有:
分别是所有点都在左侧/右侧或者左边 \(i\) 个右边 \(n-i\) 个的贡献。
考虑 \(F\) 的计算。
注意到我们当前给所有的点分成了左右两个部分,分别考虑左右两个部分的左右儿子,其实这个问题还是可以等价描述为 Trie 上,有:
- 四个儿子都有值,此时左左和右左,以及左右和右右形成了子问题
- 仅有一个儿子没有值,此时我们可以知道另一半的一个儿子是永远不会走的,还是一个子问题
- 两边都有一个儿子没有值,那么走法是固定的
既然我们并不方便计算出每一类权值出现了多少次,不妨设 \(g(h,v,x,y)\) 为高度为 \(h\) 的树,两个儿子分别有 \(x,y\) 个点,要求计算最小边权 \(\ge v\) 的方案数,这样我们仅需要保证所有子问题的最小边权都 \(\ge v\) 即可。
-
四个儿子都有值
此时分左左和右左,左右和右右两个子问题,将其方案数乘起来即可。
譬如我们枚举左左和右左分别有 \(i,j\) 个,\(0<i<x,0<j<y\),那么这个方案数就是 \({x\choose i}{y\choose j}g(h-1,v,i,j)g(h-1,v,x-i,y-j)\)
-
仅有一个儿子没有值或者两个儿子没有值
此时我们走法是确定的。
分类讨论递归即可计算。注意需要乘上组合数的系数。
考场上的失误主要是有了一个思路便急于求成,一直往下推,并未停下看看,可能你已经得到的结论,会存在更明显的,更快捷的,更简单的正解的路。
得到重要结论后不妨回头看看,寻找更简单的子问题划分方式,这很重要,也导致了我并未做出此题*
22th D
给定序列 \(A,m=|A|\),求所有 \(|B|=n\) 的好序列 \(B\),\(A\) 在其中出现次数之和(即有多少个子区间与 \(A\) 相同)
定义序列 \(B\) 是好序列,当且仅当满足:
- \(B\) 的每个组成元素是 \([1,k]\) 的正整数
- 不存在子区间 \(B[i,i+k-1]\) 是一个 \(k\) 的排列。
考虑容斥,如果没有好序列的限制,那么有枚举 \(A\) 的每个出现位置 \(i\),剩余位置都会有 \(k^{n-m}\) 种取法,所以总次数是 \(k^{n-m}(n-m+1)\)
md经典结论不知道
那么我们分类讨论求 B不是好序列的匹配次数和:
-
\(A\) 是好序列
则 \(B\) 一定是好序列,所以答案就是上面那个式子。
-
\(A\) 含重复元素
这说明如果 \(B\) 即使是好序列,那么这个排列也不会跨过 \(A\),考虑求将 \(A\) 接入一个 \(n-m\) 的序列后仍然不是好序列的方案数。
记 \(l\) 为 \(A[1,l]\) 无重复元素的最大 \(l\),\(r\) 为 \(A[r,m]\) 无重复元素的最小 \(r\),则我们可以枚举拼接序列的长度,例如用一个长为 \(x\) 的序列接在 \(A\) 头部,长为 \(n-m-x\) 的序列接在 \(A\) 尾部。
所以可以设 \(f_{i,j}\) 为填完了 \([1,i]\),最后极大的 \(j\) 个元素两两不同的非好序列个数,分别初始化 \(f_{0,l}=1\) 得到接在头部的方案数,\(f_{0,r}=1\) 得到接在尾部的方案数,答案就是一个长度的卷积形式。
这个 \(dp\) 是容易的:
\[f_{i,j}=f_{i-1,j-1}(K-j+1)+\sum_{t\ge j}f_{i-1,t} \]可以后缀和优化到 \(O(nK)\)
-
\(A\) 不含重复元素
由对称性可知 \(A\) 有 \({K\choose m}m!\) 个等价形式,所以不妨计算所有非好序列中长度为 \(m\) 的元素两两不同的段个数之和,除掉这个数就可以得到答案了。
不妨设 \(f_{i,j}\) 为填完了 \([1,i]\),最后极大的 \(j\) 个元素两两不同的非好序列个数,\(g_{i,j}\) 定义类似,但是这样的序列中 \(\ge m\) 的段的个数之和
\[\begin{cases} f_{1,1}=1,g_{1,1}=K[m\le 1]\\ f_{i,j}=f_{i-1,j-1}(K-j+1)+\sum_{t\ge j}f_{i-1,t}\\ g_{i,j}=g_{i-1,j-1}(K-j+1)+\sum_{t\ge j}f_{i-1,t}+f_{i,j}[m\le j]\\ \end{cases} \]同样可以后缀和优化,答案为 \(\frac{\sum g_{n,j}}{{K\choose m}m!}\)
感觉后面好套路啊,被第一步卡住了。。。后面完全会的。
23th D
考虑先对树进行黑白染色,然后就变成了交换相邻两个点的颜色。
你考虑一条边的贡献,它显然至少需要操作断掉这条边后两棵子树里黑色点个数差次(换一个黑点过去白点过来)。将这个过程进行贪心或者是dp都可以说明取到这个下界。
那么我们不妨设 \(cnt_{x,0/1/2,0/1}\) 表示子树内 \(0/1/?\) 在序列 \(a/b\) 出现次数,那么显然这条边的贡献是我们分别枚举两个序列子树内外有多少个问号变成 \(0\):
现在可以 \(\sum siz\)。
然后考虑简化
这个表达,显然可以将 \(d\) 变成 \(cnt_{x,2,0}-d\),得到:
令 \(S=alla_2+allb_2,T=alla_2+alla_0-allb_0\),令 \(x=cnt_{x,2,0}+cnt_{x,2,1},y=cnt_{x,2,0}+cnt_{x,0,0}-cnt_{x,0,1}\)
拿掉常数 \(2\)。
有:
如何计算它,一个自然的想法是拆掉绝对值式,也就是有:
我们设 \(g(x,y)=\sum_{d=0}^y{x\choose d}{S-x\choose T-d},h(x,y)=\sum_{d=0}^y{x\choose d}{S-x-1\choose T-d-1}\)
则有:
而 \(g,h\) 是同类的东西,只有两个参数 \(S,T\),所以下面我们只讨论 \(g\),\(h\) 可以通过定义结构体等方法实现。
而我们考虑若能够 \(O(1)\) 地移动 \(g\) 的 \((x,y)\) 端点。
显然我们可以 \(O(1)\) 移动 \(y\),考虑 \(x\)。
注意到 \(g(x,y)\) 的一个组合意义是:
有 \(S\) 个物品,你需要从中选出 \(T\) 个,要求前 \(x\) 个物品里最多选出 \(y\) 个。
考虑 \(f(x+1,y),f(x,y)\) 的差异就是:选中了第 \(x+1\) 个物品作为第 \(y+1\) 个。
这部分的方案数显然是 \({x\choose y}{S-x-1\choose T-y-1}\)
所以 \(f(x+1,y)=f(x,y)-{x\choose y}{S-x-1\choose T-y-1}\)
那么就做完了。
参考代码 code
没做出来竟然是因为没看这个题,但是推导是耗时的。基本独立补题时常 2h,推导1h,写代码20min左右,调试40min左右
计算能力需要加强
24th D
有一个zz告诉我这题点分树2log,而我不够坚定直接掐死了我想到的分块思路。
补题知道用分块后独立完成,大约用时 95 min。
5e4 直接上根号log
考虑到用 \(dfs\) 序拍平后,操作 \(1\) 其实就是一个二维偏序的修改,操作 \(2\) 就是一个二维偏序的查询,而操作 \(3\) 是可以暴力重构的。
我们考虑将当前新加入点单开一个块,当块长与普通块长度相同后暴力重构。
将点按照 \(dfs\) 序进行排序,块内按照深度排序,维护每个元素在块内排序后的位置,对每个块开一个线段树(卡常必备),进行暴力维护,同时暴力扫描新加入的点。
如果是对新加入的点(新块)进行查询和修改,可以直接子树内暴力,而如果是对老点进行查找,为了方便判断子树关系,我们可以让新加入的点的 \(dfs\) 序暂时与其父亲相同。
总操作复杂度 \(O(n\sqrt {n\log n})\),调整块长即可。
25th D
差分是可以想到的,但是后面的差分轻儿子和重儿子贡献是第一次见。
树上统计问题往往可以使用差分简化
实现难度较高,大概写了半小时,调了大半小时,从开写到过用了 80min 左右。
设询问答案为 \(f(u,v,d)\),容易发现答案可以差分为 \(f(1,u,d)+f(1,v,d)-2f(1,lca(u,v),d)+f(lca(u,v),d)\)
子树内与子树外距离的转化
单个点的答案容易点分树求解,考虑 \(f\)。
利用重链剖分维护整个子树贡献以及轻儿子贡献(类似动态dp),那么我们只需要计算 \(O(\log n)\) 个贡献,也就是跨过轻边时需要容斥。
设 \(son_u\) 是 \(u\) 树上的重儿子,\(g(u,d)\) 为轻儿子树内距离 \(u\) 不超过 \(d\) 的节点个数,\(h(u,d)\) 是整个子树内(包括自己)距离 \(u\) 不超过 \(d\) 的点的个数,容易发现如下关系:
我们可以利用函数式编程,离线下所有的 \(h,g\) 的查询,对于 \(g\),可以暴力处理轻儿子子树内所有点,并离线后通过树状数组进行深搜扫描求得,至于 \(h\),也可以通过线段树合并与区间查询进行计算。
总复杂度 \(O(n\log^2 n)\)
亲爱的,感谢这世界始终有你。
让我能,去发现世界的偶然与惊奇
如果那天我们,都不曾让心与心相遇
怎么会有,曼妙的风景
——《亲爱的》
29th C
相当有意思的题目,也是我不会的题目
首先必然是给 \(x\) 减去 \(1\)。
考虑答案集合的上三角基,也就是标准基,有将其排序后按照 \(x\) 二进制分解后选相应位置异或后所得 \(y\),因此我们根据 \((x_i,y_i),(x_j,y_j)\) 可以推出 \((x_i\oplus x_j,y_i\oplus y_j)\)
这启发我们根据 \(x\) 建立线性基,也就是建立线性基,同时维护 \(rk,num\) 两个元素,同时插入 \((x,y)\) 时,若最终不能成功插入且 \(x=0,y\neq 0\),或者 \(x\neq 0,y=0\) 都是非法的,无解。
再将这个线性基化为标准基,则我们将 \(m\) 个限制化为了 \(n\) 个最高位不同的限制。
考虑这样的一对限制 \((rk_i,num_i)\),也就是最高位为 \(i\),当前线性基里存下的排名和数字。
同时对于答案求算,我们都算标准基
这给出了如下信息:
- 答案线性基里,\(highbit(rk_i)\) 必须取 \(highbit(num_i)\) 这一位
- 对于 \(num_i\) 低于最高位且为零的位置 \(t\),也就是 \(t<highbit(num_i),(num_i)_t=0\),这说明我们选择的答案标准基里相应的位置最终异或时这个位必须是零,那么告诉我们参与这个值异或的答案基位置最高位都不能是 \(t\)。
- 对于 \(t<highbit(num_i),(num_i)_t=1\),这说明不参与这个值答案异或的答案基位置最高位不能够是 \(t\)
考虑这是否充分(这显然必要)
一个从低到高确定线性基的过程,当我们确定答案基第 \(i\) 小数,其最高位为 \(j\) 时(首先保证这玩意合法),如果有第一个信息提出的限制,根据已经填了的信息可以直接推知这个值,也就是说这是定值。如果没有第一个信息提出的限制,则有 \(j-i\) 个二进制位可以任意填写(有 \(i\) 个必须是 \(0\) 的位,标准基嘛)
所以,根据 \(rk,num\) 的信息,我们可以求出数组 \(can[i,j]\) 表示答案基第 \(i\) 小数其最高位是 \(j\) 是否可行,以及 \(fixed_i\) 表示第 \(i\) 小,其最高位和值是否已经确定。
那么有 dp:设 \(f_{i,j}\) 表示现在已经填了答案基的前 \(i\) 小数字,最高位是 \(j\)。
考虑转移:
- \(can[i,j]=1\)
- 令转移系数 \(w\) 当 \(fixed_i=1\) 时 \(w=1\),否则 \(w=2^{j-i}\)
- \(f_{i,j}=w\sum_{k<j} f_{i-1,k}\)
最终答案是考虑所有 \(rk\) 限制的最高位 \(mxh\),最少填到这里,最多填到 \(n\),因此答案是: