题解|2023暑期杭电多校09
1002.Shortest path
签到题 DFS记忆化搜索
题意
给定一个正整数 $n$ ,可以对其进行以下操作:
- 如果 $n$ 能被 $3$ 整除,则可以使 $n=n/3$ ;
- 如果 $n$ 能被 $2$ 整除,则可以使 $n=n/2$ ;
- 使 $n=n-1$
求使得 $n$ 变成 $1$ 的最少操作次数
解题思路
将样例Output输出即可
这题不难,但确实精彩()//毕竟……
《钉耙编程”中国大学生算法设计超级联赛》是由hdu自主研发的一款全新开放世界冒险竞赛。竞赛发生在一个被称作“hdu”的幻想世界,在这里,被编译器选中的人将被授予“C++”,导引代码之力。你将扮演一位名为“acmer”的神秘角色,在自由的打题中邂逅性格各异能力独特的STL容器,和他们一起击败强题,找回AC的代码
不闹了,解题吧
不难看出操作 $3$ 的收益最低,是不满足操作 $1,2$ 的时候凑条件用的。
而由于只允许整除,操作 $1,2$ 的优劣性不好评估(因为要夹杂操作 $3$ 而不单纯是减少的量的区别),因此每次对本次进行的两种操作方案进行比较。
按以下操作递归处理 $n$ :
- 如果 $n=1$ ,则返回 $0$ ;
- 进行若干次(可能0次)操作 $3$ 使得 $n$ 能被 $2$ 整除,执行操作 $2$
- 进行若干次(可能0次)操作 $3$ 使得 $n$ 能被 $3$ 整除,执行操作 $1$
由于数据范围的关系,传统的DFS会超时,因此需要使用记忆化搜索
即每次计算完某个数(记为 $x$ )的结果,将其保存下来,后续搜索 $x$ 时就无需继续搜索到底部,直接输出这个数的结果即可
记忆化搜索可以用 map 实现,频繁读取而不考虑元素顺序的可以使用 unordered_map ,有效降低时间空间复杂度
第2、3行的提交使用了 map ,代码完全一致;第1行的提交仅仅将 map 改为了 unordered_map
时间复杂度
$O(t\log^2n)$
参考代码
1 | unordered_map<ll,ll> mp; |
1005.List Reshape
签到题、模拟
题意
按一定格式给定一个纯数字一维数组,按给定格式输出成二维数组。
解题思路
读入初始数组字符串,将每个数字分离,按要求输出即可
参考代码
1 |
|
1008.Coins
概率论
题意
$n$ 个人进行游戏,每个人初始有 $a_i$ 个硬币,每次随机选择一个人给另一个人一枚硬币
若某人给出硬币后没有剩余,则退出游戏。直到有人拿到所有硬币游戏结束
求游戏轮数的数学期望
解题思路
概率论还没学()官方题解的鞅论看不懂(躺)//
等学完回来给严格推导(手搓大饼ing)
ACMer三大美德:暴力、打表、猜结论//下面给出道德解法()
假设现在只有两个人,那么每个人给对方硬币的概率都为50%,直到其中一人没有硬币为止。
设这两个人的硬币数分别为 $m,n$ ,则游戏轮数期望为:
$f(m,n)=1+\dfrac{1}{2}f(m+1,n-1)+\dfrac{1}{2}f(m-1,n+1)$
可以发现越往后对期望的贡献越低,限制递归深度,利用如下程序暴力打表:
1 | double f(ll m,ll n,ll rnd){ |
得到以下打表结果(不得不说跑的是真慢):
1 | in:1 3 out:3 |
暴力打完表可以猜结论了: $f(m,n)=mn$ ,即对于两个人,答案是他们硬币数的乘积;
那么对于三个人,利用样例in:1 1 1 out:3
盲猜是 $a_1a_2+a_1a_3+a_2a_3$
推广到 $n$ 个人,两两相乘再相加即可
由于数据较大,答案需要开int128才能放得下
另外结合数据范围,利用前缀和算出结果即可
时间复杂度
前缀和&求和:$O(n)$
参考代码
1 | void solve() |