牛客挑战赛 64 解题报告

A

两种做法,第一种是建出完整图的最小生成树,可以发现最小生成树上点 到点 的路径上最小边权就是点 的答案。时间复杂度

第二种做法是使用并查集维护连通块,某个连通块与点 联通时就更新答案,启发式合并即可。时间复杂度

B

首先我们可以写出一个简单的暴力:根据汉诺塔的常规套路,将除了最大盘之外的盘子堆到除 最大盘所在柱 的另一个非目标柱上,然后将最大盘移动到目标柱上,不断递归下去即可。

具体地说,假设当前需要将 号盘从 移动到 柱,那么我们将 号盘全部堆到除 外的那个柱子上,然后再将 号盘堆到 上即可。

代码如下:

#include <bits/stdc++.h>

using namespace std;

int n, b[65];

void dfs(int k, int t) {
    if (b[k] == t) return ;
    for (int i = k - 1; i; i--) dfs(i, 3 - b[k] - t);
    b[k] = t, printf("%d %c\n", k, t + 'A');
}

int main() {
    scanf("%d", &n);
    for (int i = 2; i <= n; i += 2) b[i] = 2;
    for (int i = n; i; i--) dfs(i, 1);
    return 0;
}

然后用这个暴力打出移动次数的表,可以发现(记 个盘子时的移动次数):

直接递推即可。

C

发现如果越过距离为 ,则跳跃的路径会形成以 为起点,循环节为 的一个循环。

那么列出式子,设 ,则有:

可以通过枚举因数的倍数的方式 时间内求出, 筛法或者质因数分解求出。总时间复杂度

(一个数所有因数的和是 级别的。)

D

我们先考虑 的情况,即固定左端点求贡献。 的情况我们将序列翻转再做一遍即可。

当左端点固定时,可以发现合法的右端点一定是以 开头的一段区间,可以拆位求出该区间右端点。

那么现在我们只需要实现求以 开头一段区间的前缀最大值之和以及移动 时维护前缀最大值之和,使用线段树维护。

然后我们发现这样子做会算重 的情况,使用单调栈去重。

时间复杂度

E

考虑一张左部 个点,右部 个点的二分图,那么题意所述网格图则是将其行列对应连边。

问题转化为本质不同无标号二分图的数量。

由于每个点度数最多为 ,于是联通块的形状只有如下 种:

  1. 左部 个点,右部 个点的环。
  2. 左部 个点,右部 个点的链。
  3. 左部 个点,右部 个点的链。
  4. 左部 个点,右部 个点的链。

因为右部点一定够用,考虑以左部点数量为元的生成函数。

第一种的 GF 为 ,其余 ,简单相乘即可。

此时已经可以直接先 ln 加起来再 exp 无脑做,但是如果常数大的话可能过不去。

仔细观察发现这是五边形数的四次方取逆乘上 ,因此只需一次求逆和若干次乘法,时间复杂度

全部评论
第一题 做法一 并查集+dfs不是O(n)吗,做法二 并查集+启发式合并不是O(nlogn)吗?求教
2 回复 分享
发布于 2022-10-15 00:16 江苏
楼上的老哥,建最小生成树要一个log,以及C题,是不是不应该$\times \frac{1}{n}$??打错了??
1 回复 分享
发布于 2022-10-15 23:16 陕西
学算法,就上牛客,XCPC铜牌不是梦,心动不如行动,点此下方链接报名立减20元: 基础算法入门班:https://www.nowcoder.com/courses/cover/live/724?coupon=ARgGejk 进阶数据结构专题课:https://www.nowcoder.com/courses/cover/live/707?coupon=AQDlsi4
点赞 回复 分享
发布于 2022-12-02 20:50 天津
E 题可以使用不到 1k 的 O(n sqrt n) 做法通过,而且好像是第三快的。https://ac.nowcoder.com/acm/contest/view-submission?submissionId=54368144
点赞 回复 分享
发布于 2022-10-27 10:14 广东
a第一种做法是最大边权还是最小边权啊
点赞 回复 分享
发布于 2022-10-16 20:58 上海

相关推荐

迷茫的大四🐶:那你问他上班之后老实了没
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务