题解|2023暑期杭电多校04
1003.Simple Set Problem
思维
题意
给定 $k$ 个非空集合,在每一个集合里选择一个数 $a_i$ ,使得这些数之中最大值与最小值之差 $d=max(a_i)-min(a_i)$ 最小,输出 $d$ 的最小值
解题思路
不论哪一种选法,最小值一定是在全体元素中取到的
不妨从小到大遍历全体元素作为下界,记当前遍历元素为 $a_i$
在每一个集合中二分查找恰好大于等于 $a_i$ 的元素选入(遍历到 $a_i$ 所在集合的时候,一定会选入 $a_i$ )
找到选定元素的最大值,做差
直到某个集合中没有大于等于 $a_i$ 的元素为止(此时该集合最大的元素选入的情况已全部考虑过),最终在得到的值中取最小即可
时间复杂度
读入: $O(n)$ ;排序: $O(n\log n)$ ;遍历二分查找: $O(n\log n)$
综合时间复杂度: $O(n\log n)$
其中 $n$ 表示全体元素个数, $n\le 4e6$
参考代码
1 | void solve() |
1006.PSO
数学题、概率论
题意
给定一个星状图(中心节点与每个其他节点之间各有一条边,其他节点之间没有边),任选两个点,求它们之间的距离的数学期望以及最大距离的长度
解题思路
任选两个点的方案总数为 $C_n^2=n(n-1)/2$
其中一个点是中心点的方案数为 $n-1$ ,距离是 $1$
其余方案数为 $n(n-1)/2-(n-1)$ ,距离是 $2$
因此任选两个点的距离期望为:
$$\begin{align}
E&={[n(n-1)/2-(n-1)]\times2+(n-1)\times1}/C_n^2 \newline
&=[n(n-1)-(n-1)\times2+(n-1)]/C_n^2 \newline
&=(n-1)^2/C_n^2 \newline
&=2(n-1)/n
\end{align}
$$
注意控制精度
参考程序
1 | void solve() |
1007.Guess
莫比乌斯函数
题意
给定一个正整数 $n\le1e18$ ,求 $e^{S(n)}$
其中,$S(n)=\sum\limits_{d|n} \mu(\dfrac{n}{d})\ln(d)$ ,$e$ 是自然对数 $\ln$ 的底数,$\mu(x)$ 是莫比乌斯函数,答案取模
前置知识点
莫比乌斯函数:
$$
\mu(n)=\begin{cases}
1 &,n=1; \newline
0 &,n含有大于1的完全平方因子; \newline
(-1)^k &,n为k个质数的乘积 \newline
\end{cases}
$$
解题思路
对于 $n$ 的因数 $d$ ,根据 $\dfrac{n}{d}$ 与 $d$ 的轮换对称性可知:
$S(n)=\sum\limits_{d|n} \mu(\dfrac{n}{d})\ln(d)=\sum\limits_{d|n} \mu(d)\ln(\dfrac{n}{d})$
对 $S(n)$ 做一次莫比乌斯变换(第一形式)可得:$\ln(n)=\sum\limits_{d|n} S(d)$
两边以 $e$ 做底数得 $e^{ln(n)}={e}^{\sum\limits_{d|n} S(d)}\Rightarrow n=\prod\limits_{d|n} e^{S(d)}$
右式是一个连乘积,其连乘长度为 $n$ 的全体因数个数
记 $F(x)=e^{S(x)}$ ,那么答案也就是在求 $F(n)$
根据上式:
- $1=F(1)\Rightarrow F(1)=1$
- 对于任意质数 $x$ ,$x=F(1)F(x)\Rightarrow F(x)=x$
- 对于任意合数 $x$ ,借助 $1,2$ 递归计算出 $F(x)$
经过较长时间的感性理解,想到了一种遍历求 $F(x)$ 方法的伪代码如下:
1 | F[]={0} |
(其实打表也挺好的,想个一般性的方法好难qwq)
可以得到以下 $F(x)$ 的正整数序列:
$1,2,3,2,5,1,7,2,3,1,11,1,13,1,1,2,17,1,19,1,1,1,23\cdots$
这个序列的意义是 $x$ 对乘积 $n$ 的贡献,回到上面看那个连乘积的长度和表达形式就非常合理了
通项公式为:
$$\begin{align}
F(n)&=lcm{1…n}/lcm{1…n-1} \newline
&=\begin{cases}
n&,n=p^i,p是素数,i\in \N_+ \newline
1&,Otherwise
\end{cases}
\end{align}
$$
即为最终答案
面对 $n\le 1e18$ 的庞大数据,问题就落到了如何快速求出 $F(n)$ 上了。根据通项公式,只需要判断 $n$ 是否有且只有一个素数非平凡因子 $p$ 即可
Pollard-Rho算法是一种用于因数分解整数的快速随机算法,它可以实现在 $n^{\frac{1}{4}}$ 的时间下随机找到一个 $n$ 的非平凡因子
其中用到了Miller-Rabin 素性测试算法,是一种测试素数的快速随机算法
Pollard-Rho算法的具体实现可以参考这篇博文:大数因数分解Pollard_rho 算法详解
最终根据查找结果,结合通项公式判断输出即可
参考代码
(Pollard_Rho算法及Miller_Rabin算法部分略)
1 | ll fac=0; |
1010.Kong Ming Qi
猜结论题 找规律题
题意
如题,游戏规则和孔明棋相似
在一个 $(n+2)\times(m+2)$ 大小的棋盘的中间 $n\times m$ 的格子里放置着一些棋子
每次行动可以选择一个有四面相邻的棋子,使其跳过相邻的棋子,并使被跳过的棋子从棋盘上被移除
问对于给定的 $n,m$ ,剩余棋子个数最少是多少
解题思路
首先考虑只有一行/一列的情况,每次只能选择倒数第二个跳出。假设 $n=1$ ,连续模拟几次可知一定剩余 $\lceil m/2 \rceil$ 颗棋子
对于多行多列的情况,可以考虑以下两个基础操作:
- 每次消去 $1\times 3$ 区域的棋子(需要左下方有棋子,中间操作)
- 每次消去 $2\times 3$ 区域的棋子(最终操作)
连续操作 $1$ 后操作 $2$ ,即可在行数/列数大于 $3$ 的情况下任意消除 $3$ 行/列
考虑小情况 $2\times 2,2\times 3,3\times 3,2\times 4,3\times 4$ 等,借助上述基础操作以及模拟可得,当 $m,n$ 中有一个为3时,最少剩余 $2$ 颗棋子,其他情况最少剩余 $1$ 颗棋子,依此打表
参考程序
1 | void solve() |
1011.Circuit
图论-最短路-Floyd
题意
给定一个无重边、无自循环的带权有向图 $G=(V,E),|V|=n,|E|=m$
求 $G$ 的所有回路中最短回路的长度以及个数,个数取模
解题思路
全图范围的最短路计数,考虑使用弗洛伊德算法//
为了不重不漏的计数,考虑每个最短回路仅在其最大标号处计数
对于一条有向回路,可以将其最大编号到下一点的有向边单独分割出来,剩余部分即为从起点到回路上最大编号点的最短路//
借助Floyd算法,在 $O(n^3)$ 的时间内,计算最短路的同时,可以进行最短路方案数的计数,这里详细阐述一下计数过程
原图 $G$ 存在有向边 $u\rightarrow v$ ,则 $u\rightarrow v$ 的初始方案数置为 $1$ ,没有边则置为 $0$
加入点 $k$ 时,过点 $k$ 的 $i\rightarrow j$ 的最短路的方案数为: $i\rightarrow k$ 的最短方案数 $\times$ $k\rightarrow j$ 的最短路方案数
如果发生最短路更新,则方案数一并更新//另判断如果长度一致,则方案数需相加
每次完成更新后,假设 $k$ 已经是以 $i$ 为起点的最短回路上的最大编号点了,此时原图 $G$ 中如果有 $k\rightarrow i$ 的有向边,则可以构成回路,比较计数即可//
更加具体的内容可以参考代码注释
温馨提示: $INF$ 的值需要设置到 $1e18$ ,因为两段方案数乘积最大可以为 $MOD^2 \approx 1e18$ ,补题时因为 $INF$ 的值不够大卡了两个小时左右
时间复杂度
Floyd算法:$O(n^3)$
参考代码
1 | const long long INF=1e18; |
1012.a-b Problem
贪心
题意
给定一堆 $n$ 个石子,每个石子有非负值 $a_i,b_i$ ,分别代表Alice和Bob取该石子可以得到的分数
两人都希望自己的得分最大化,Alice执先,求最终Alice和Bob的分数差
解题思路
取某石子的价值不仅在于自身得分,也在于让对手失去他那部分的分值。因此根据每颗石子的分数之和排序,从大到小依次取即可
参考代码
1 | void solve() |