题解|2023暑期牛客多校06
A.Tree
图论-Kruskal、动态规划
题意
给定一棵 $n$ 个节点带点权和边权的无根树
节点具有颜色白($0$)和黑($1$),颜色可反转,所需代价 $cost_i$ 为该点点权
整棵树的 $earning$ 为 $\sum\limits_{u\in V_0}\sum\limits_{v\in V_1} val(u,v)$ 。其中, $val(u,v)$ 为节点 $u\rightarrow v$的最短路径上的最大边权, $V_0$ 为白色点集, $V_2$ 为黑色点集
可以操作反转节点颜色任意次,求最大 $earning-\sum cost$ (以下简称 $score$ )
解题思路
注意到对于每对黑白点对,其贡献为最短路径上的最大边权。考虑利用Kruskal算法对树进行重构,即按边权从小到大的顺序进行加边
可以发现,在加入某条边 $e_i$ 时,原本在同一连通分量中的黑白点对的 $score$ 不受影响。由于加边顺序,新加的边一定具有目前最大的边权,因此只有经过新加的这条边的点对才对 $score$ 具有贡献,每个点对的贡献值为 $w_i$ ,点对数量为:$左白\times右黑+左黑\times右白$
构造dp数组:定义 $dp_{i,j}$ 为连通分量 $i$ (以并查集中连通分量的根节点标识)中具有 $j$ 个白色节点时的最大 $score$ 。初始对于点 $i$ ,$dp_{i,color_i}=0$ (不变);$dp_{i,color_i\oplus 1}=-cost_i$ (反转)
在合并 $A、B$ 两个连通分量到 $C$ 时具有以下转移方程:
$$
dp_{C,i}=\max\limits_{0\le k \le |A| \And 0\le i-k\le |B|}{dp_{A,k}+dp_{B,i-k}+w(k(|B|-(i-k))+(i-k)(|A|-k))}
$$
(两边原有的 $score$ 加上过新加边的 $score$ )
可以结合代码注释进行理解
时间复杂度
$O(n^2\log n)$
参考代码
1 | struct edge{ |
B.Distance
数学、贪心(?)
题意
对于两个大小相同的多重集 $\mathbb{A},\mathbb{B}$ ,可以选择其中任一元素 $x$ 执行操作 $x=x+1$ 任意次数,最少的使得 $\mathbb{A},\mathbb{B}$ 相同的操作次数记为 $C(\mathbb{A},\mathbb{B})$
不同大小的 $\mathbb{A},\mathbb{B}$ 视为 $C(\mathbb{A},\mathbb{B})=0$
现在,给定两个大小为 $n$ 的多重集 $\mathbb{S},\mathbb{T}$ ,求对于 $\mathbb{S},\mathbb{T}$ 的所有子集 $\mathbb{A},\mathbb{B}$ ,最少操作次数之和 $\sum\limits_{\mathbb{A} \subseteq \mathbb{S}}\sum\limits_{\mathbb{B} \subseteq \mathbb{T}} C(\mathbb{A},\mathbb{B})$ 的值
具有相同值的两个元素视为不同元素,答案取模
解题思路
对于某对子集 $\mathbb{A},\mathbb{B}$ ,为了使他们相同的操作次数最少,我们会将他们排序的元素后一一对应,使每一对中较小的数变成较大的数//假设 $a_i$ 与 $b_i$ 对应,他们在这次变化中贡献的操作次数显然是 $|a_i-b_i|$
那么换一种角度考虑,对于原多重集 $\mathbb{S},\mathbb{T}$ ,任取一对数 $a_i,b_j$ ,考虑它们俩对应的方案数 $cnt_{i,j}$ ,那么它们在全部方案中贡献的总操作次数即为 $|a_i-b_i|\times cnt_{i,j}$
由于我们的操作策略是排序后对应,因此先对 $\mathbb{S},\mathbb{T}$ 进行排序//
选定两个数 $a_i,b_j$ 后,它们在 $\mathbb{S},\mathbb{T}$ 中的位置前面选 $k$ 对数的方案数为 $\sum\limits_{k=0}^{min(i-1,j-1)}C_{i-1}^kC_{j-1}^k=C_{i+j-2}^k$ (范德蒙德卷积)
同理,它们在 $\mathbb{S},\mathbb{T}$ 中的位置后面选 $k$ 对数的方案数为 $C_{2n-i-j}^k$
总方案数为 $cnt_{i,j}=C_{i+j-2}^kC_{2n-i-j}^k$ ,乘以两数之差的绝对值即为它们对答案的总贡献//
预处理组合数,枚举 $i,j$ 求和即可
时间复杂度
$O(n^2)$
参考代码
1 |
|
C.idol!!
数学
题意
正整数 $n$ 的双阶乘 $n!!$ 表示不超过 $n$ 且与 $n$ 有相同奇偶性的所有正整数乘积
求对于给定 $n$ ,$\prod\limits_{i=1}^n i!!$ 的后缀 $0$ 个数
解题思路
根据双阶乘的性质,可以得到: $(n-1)!!\times n!!=n!$
因此对于给定的 $n$ ,原式可化为:
$$\prod\limits_{i=1}^n i!!=\begin{cases}
\prod\limits_{i=1}^\frac{n}{2} (2i)! &,n为偶数 \newline
\prod\limits_{i=1}^\frac{n+1}{2} (2i-1)! &,n为奇数
\end{cases}$$
显而易见的,阶乘中因子 $2$ 的个数一定多于因子 $5$ 的个数,因此题目等价于求上式中因子 $5$ 的个数//
考虑某单一阶乘 $n!$ 中所含因子 $5$ 的个数。
可以发现,每个 $5$ 的倍数项会提供 $1$ 个因子 $5$ ,共有 $\lfloor \dfrac{n}{5} \rfloor$ 项
除此之外每个 $25=5^2$ 的倍数项会额外提供一个因子 $5$ ,共有 $\lfloor \dfrac{n}{5^2} \rfloor$ 项
再除此之外每个 $125=5^3$ 的倍数项会额外提供一个因子 $5$ ,共有 $\lfloor \dfrac{n}{5^3} \rfloor$ 项……
因此对于单一阶乘 $n!$ ,其提供因子 $5$ 的数量 $cnt_5=\sum\limits_{i=1}^N \lfloor \dfrac{n}{5^i} \rfloor (5^N>n)$
接着考虑连乘积中因子 $5$ 个数的总和。
$$
ans=\begin{cases}
\sum\limits_{i=1}^\frac{n}{2} \sum\limits_{j=1}^N \lfloor \dfrac{2i}{5^j} \rfloor=\sum\limits_{i=1}^N \sum\limits_{j=1}^\frac{n}{2} \lfloor \dfrac{2j}{5^i} \rfloor &,n为偶数 \newline
\sum\limits_{i=1}^\frac{n+1}{2} \sum\limits_{j=1}^N \lfloor \dfrac{2i-1}{5^j} \rfloor=\sum\limits_{i=1}^N \sum\limits_{j=1}^\frac{n+1}{2} \lfloor \dfrac{2j-1}{5^i} \rfloor &,n为奇数
\end{cases} \newline
$$
对于某一 $i$ ,发现不论 $n$ 的奇偶, $j=1$ 开始的每 $5^i$ 项之和构成公差为 $2\times5^i$ 的等差数列//
例:$i=1$ ,$n$ 为偶数且足够大时,$\lfloor \dfrac{2j}{5^i} \rfloor$ 的前 $15$ 项如下,其中每 $5$ 项之和构成公差为 $5\times 2$ 的等差数列: $0,0,1,1,2||2,2,3,3,4||4,4,5,5,6……$
经计算,对于某一 $i$ ,等差数列的首项为
$$
a_1=\begin{cases}
\lfloor \dfrac{5^i}{2} \rfloor+2 &,n为偶数 \newline
\lfloor \dfrac{5^i}{2} \rfloor+1 &,n为奇数
\end{cases}
$$
完整的段用等差数列求和,非完整的段手算一下//
若此前完整段的数量记为 $m$ ,则非完整段:
前 $\lfloor \dfrac{5^i}{2} \rfloor$ 项的值为 $2m$ ,
第 $\lfloor \dfrac{5^i}{2} \rfloor+1$ 至 $2\times\lfloor \dfrac{5^i}{2} \rfloor $ 项的值为 $2m+1$(手搓一下就知道了)
求和即可
令 $N=\lfloor \log_5n \rfloor+1$ ,对 $i\in[1,N]$ 遍历求和得到答案
由于答案数据极其庞大,超出了C++ %lld(64bits)的范围,因此需要使用更高位数的整数类型(如int128)//或者直接转战Python
时间复杂度
$O(\log n)$
参考代码
1 | import math |
E.Sequence
思维题
题意
给定一个长度为 $n$ 的正整数序列,并进行 $q$ 次询问
每次询问给定一个范围 $[l,r]$ 和一个正整数 $k$
问能否将序列中给定范围内的子序列划分为 $k$ 段非空区间,且每段区间之和为偶数
解题思路
首先对于给定区间:
- 给定区间内总元素个数不足 $k$ ,则无法划分
- 给定区间内奇数元素个数为奇数,则给定区间的和为奇数,无法划分为 $k$ 个和为偶数的区间
- 给定区间内奇数元素个数为偶数,则最优划分为:从前往后奇数两两匹配形成区间,余下的偶数自成一个区间
因此本题的关键就在于区间内奇数的处理
输入的记录奇数所在的位置,每次询问对于给定的区间,二分查找第一次出现奇数的位置和最后一次出现的位置,判断奇数个数
符合要求再进行区间计数判断,具体实现和解释可以参考代码注释
时间复杂度
2023/8/5:纠正:最坏时间复杂度为 $O(qn)$ ,卡一下平均能过qwq
参考代码
1 |
|
G.Gcd
数论
题意
给定一个包含两个非负数的初始集合 $S={x,y}$
每次操作可以选定其中不相等的两个数 $a,b$ ,并将 $a-b$ 或 $gcd(a,b)$ 置入集合 $S$ ,其中 $gcd(0,a)=a$
可以操作任意次,问能否使得集合 $S$ 包含非负数 $z$
前置知识点
解题思路
根据裴蜀定理,两个正整数辗转相减只能得到他们最大公约数的倍数//
因此对于 $z$ ,判断其是否是 $g=gcd(x,y)$ 的倍数即可。
如果 $z$ 是 $g$ 的倍数,则可以通过以下操作得到 $z$ :
- 将 $g=gcd(x,y)$ 置入集合
- $x$ 作为 $g$ 的倍数,其加减任意次 $g$ 便可得到任意 $g$ 的倍数。
只能减不能加怎么办呢//先把 $x$ 减到 $-g$ 就好了
值得注意的是,本题的数据约束为非负数,这意味着需要对 $0$ 的情况进行特判//
- 对于 $z=0$ ,仅当 $x,y$ 有 $0$ 时有解
- 对于 $x=0$ 或 $y=0$ ,仅当 $z$ 为非 $0$ 项的倍数时有解(实际上这条也满足裴蜀定理,直接归入一般情况即可)
参考样例:
1 | in: 1 0 1 2 |
参考代码
1 | void solve() |