CF686_Div3题解
D
解题思路
首先我们将$n$进行素因子分解,得到如下的表达式:
$$n = p_1^{\alpha_1}p_2^{\alpha_2}…p_l^{\alpha_l}$$
假设我们得到的$k$个数进行素因子分解,得到的结果是:
$$a_i = p_1^{b^i_1}p_2^{b^i_2}…p_l^{b^i_l}$$
由于后面的数都可以整数前面的数,所以有
$$b^i_{j} \le b_{j}^{i+1} \quad \forall i, j$$
$$\sum_{i=1}^{k}b^i_{j} = \alpha_j$$
所以可以看到,$K$的最大值取决于$\alpha$的最大值。
在构造的时候,我们令前$k - 1$个数都是指数最大的那个素因子,最后一个用整个除以前面的即可。
时间复杂度$O(\sqrt{n})$
C++代码
1 |
|
E
解题思路
$n$个节点,$n$条边的连通图,是在一棵树的基础上增加一条边得到的结果。
得到的图也可以看做是一个环,然后换的每个节点上面挂了一棵树,就像下面的图一样。

然后我们考虑每棵树内部节点的贡献。
对于蓝色所标的子树中的节点而言,其内部两个点之间只有一条路径,所以答案是$\frac{cnt_i * (cnt_i - 1)}{2}$
从蓝色节点到任何一个其他节点,都存在两条不同的路径,所以路径条数为$2 * cnt_i * (n - cnt_i)$
但是在统计每个子树的时候,第二种路径会被统计两次,所以最终的答案就是
$$\sum_{i} ( \frac{cnt_i * (cnt_i - 1)}{2} + cnt_i * (n - cnt_i) )$$
为了统计每棵子树的大小,可以使用tarjan算法。这里可以用一个简单的方法,模仿拓扑排序的思想。从叶子节点向里面扩展。具体方法参考下面的代码。
C++代码
1 |
|
F
解题思路
先使用ST表处理,便于在$O(1)$的时间内得到任意一个区间的最大最小值。然后首先枚举第一个分界点。
利用单调性,两次二分找到使得第二个区间满足的左右边界。在利用单调性二分找到第三个区间满足的点即可。
时间复杂度$O(n \log n)$
C++代码
1 |
|