牛客复盘] 2023河南萌新联赛第(七)场:信息工程大学 B\I 20230823

总结

  • 场外OB做了B和I题,只能说这场有点离谱。
  • B 并查集缩点+图的直径(max(最短路))
  • I 分解质因数贪心(二分也可以)

  • 另外据说C题也离谱,出题人拿洛谷第一篇题解造的数据,但那篇题解是错的,评论区有人hack了给出反例。

B 七夕

链接: 七夕

1. 题目描述

在这里插入图片描述

2. 思路分析

这题描述挺清晰的,可惜说反了。正确的表述可以看我代码里的注释。
一个错误的思路是直接0-1bfs,但题目没给起始点,起始和结束可以是最坏点,所以不能做。实际题目要求的是最长路(最坏)。
  • 先用dsu缩点,如果两个城市可以用城际公交到达,那么这俩可以看做一个城市,没有移动代价。
    • 于是很容易想到用并查集把所有城市合并成一个一个城市群,再把城市群作为图里的节点。
  • 那么问题就转化成城市群这个图的最长路,这个实际上是图的直径,可以用两次bfs的方法做。
    • 结论:从任意一点出发bfs,最远端的点,一定是一条直径的一个端点。
    • 那么就可以第一次bfs求一个端点;第二次求直径长度。

  • 代码实现时,把节点-1转化成0-indexed。
  • 缩点后,用每个家族的代表元参与城市群的建图。

3. 代码实现

PROBLEM = """链接:https://ac.nowcoder.com/acm/contest/63746/B

七夕节左近,楚楚想去见女朋友,可是他最近和女朋友吵架了,女朋友躲着他,不知道会出现在哪座城市里。楚楚心知肚明女朋友是在赌气,所以无论自己在哪座城市,女朋友在哪座城市,
他一定要在七夕节见到她。城市之间用铁路或者城际公交中的一种相连通,虽然并不是任意两个城市都直接相连,但是保证可以通过这两种交通方式从任一城市出发到另一任意城市。
由于楚楚的特殊身份,他可以免费乘坐城际公交,那么他最少需要买多少张火车票才能保证见到女朋友呢?
输入描述:
第一行三个整数n,k,m,表示共n个城市,编号从1到n,k条城际,m条铁路。
接下来k行,每行两个整数u、v,表示城市u、v之间有城际。
再接下来m行,每行两个整数u、v,表示城市u、v之间有铁路。

输出描述:
一个整数表示还需要的票数。
输入
6 3 4
1 2
2 3
4 5
1 3
3 4
4 6
5 6

输出
2
"""


#       ms
def solve():
    n, k, m = RI()
    fa = list(range(n))

    def find(x):
        t = x
        while x != fa[x]:
            x = fa[x]
        while t != x:
            t, fa[t] = fa[t], x
        return x

    for _ in range(k):  # 读k个城际,缩点
        u, v = RI()
        u, v = find(u - 1), find(v - 1)
        fa[u] = v

    g = [[] for _ in range(n)]
    for _ in range(m):  # 读m个铁道,给代表元建图;重边和自环都不管,直接建
        u, v = RI()
        u, v = find(u - 1), find(v - 1)
        g[u].append(v)
        g[v].append(u)

    def bfs(st):  # 层序遍历
        q = [st]
        vis = [0] * n
        vis[st] = 1
        step = 0
        while q:
            nq = []
            step += 1
            for u in q:
                for v in g[u]:
                    if not vis[v]:
                        vis[v] = 1
                        nq.append(v)
            q = nq
        return u, step - 1  # 两次bfs求图的直径,就是max(最短路)

    st, _ = bfs(find(0))  # 第一次bfs求直径的一段
    _, ans = bfs(st)  # 第二次bfs求直径长度
    print(ans)

I 细胞分裂

链接: 细胞分裂

1. 题目描述

在这里插入图片描述

2. 思路分析

一眼贪心,然而提交wa。
赛中一众大佬都过不了,赛后看ac的代码,全都长得一样而且相当复杂,连注释都没改,经神秘群友调查,发现出自隔壁一篇csdn。
另外由于这是一道原题,在洛谷和其他oj网站上提交自己代码都能过,就牛客过不了。
赛后有群友爆出了wa的数据,经人工验证(或者用大数代码验证),那篇复杂代码的解是错的。
输入
1
39102 255398
657695640
正确输出
255398
错误ac代码输出
85133

print((657695640**85133) % (39102**255398) == 0)  # False

3. 代码实现

def solve():
    n, = RI()
    m1, m2 = RI()
    a = RILST()
    cnt = [(p, v * m2) for p, v in pt.prime_factorization(m1)]  # 对m1分解质因数计数
    if m1 == 1:
        return print(0)
    ans = inf
    for s in a:
        p = 0
        for k, v in cnt:  # s要包含m1的每个质因数,且要扩展次数达到目标次,向上取整
            c = 0
            while s % k == 0:
                s //= k
                c += 1
            if c == 0:  # 不含
                break
            p = max(p, (v + c - 1) // c)  # 向上取整
        else:
            ans = min(ans, p)  # 没有不含的才能用

    print([ans, -1][ans == inf])

六、参考链接

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值