重温经典2020ICPC上海站补题题解

注:个人补题记录 ,按难度排序

G、Problem - G - Codeforces

G是签到题比较简单看题面:

根据题意我们可以知道,我们只要统计Fibonacci数列前n项里面有多少个奇数和偶数就能算出答案,找规律就行。上ac代码

import sys

n = int(sys.stdin.readline())
ans = 0
a,b,num =n-3,n%3, n//3
ans += (a+b)*num//2
ans += (num + 1)*num
print(ans)

M、Problem - M - Codeforces

题目定义是思维题,看题面:

题目大意是说每组样例给你n和m个由‘/’分割的字符串,前n个是需要 ignored的后m个不能被 ignored,问我们最少 ignored几次能完成。就像删文件夹,一个文件夹里面如果全部都要删,那我们直接删一次总文件夹就好,负责就得将需要删的子文件夹一个一个删。理解题意之后就很容易想到递归统计我们需要的处理的次数,而建树的话,我们定义一个节点类建字典树就好。

上pypy3AC代码:

import sys

class Node:
    def __init__(self, name, ignore):
        self.name = name
        self.ignore = ignore
        self.sons = {}

    def addson(self, name, ignore):
        if name in self.sons:
            self.sons[name].ignore = ignore
            return self.sons[name]
        x = Node(name,ignore)
        self.sons[name] = x
        return x

def solve():
    n, m = map(int, sys.stdin.readline().split())
    root = Node('', False)
    for _ in range(n):
        s = sys.stdin.readline().strip().split('/')
        now = root
        for x in s:
            now = now.addson(x, True)
    for _ in range(m):
        s = sys.stdin.readline().strip().split('/')
        now = root
        for x in s:
            now = now.addson(x, False)

    def getans(x):
        if x.ignore:
            return 1
        ans = 0
        for name,y in x.sons.items():
            ans += getans(y)
        return ans

    print(getans(root))


for _ in range(int(sys.stdin.readline())):
    solve()

B、Problem - B - Codeforces

B题也是到思维吧,狠狠的考智商和思维灵活,算是由CF内味了。

这题很容易想的是搜索,但emmmmm,改一个影响周围一圈,这个数据大小肯定TLE啊QAQ。后面想了想要是a和b不同的个数小于\frac{n\cdot m}{2}那直接变成a不就好了,然后又想到对于 . 和X的关系是没有方向的所以,如果不同的字符超过\frac{n\cdot m}{2},那我们就把a取反输出就好了,看代码:

import sys

n,m = map(int, sys.stdin.readline().split())
a,b = [], []
for i in range(n):
    a.append(sys.stdin.readline().strip())
for i in range(n):
    b.append(sys.stdin.readline().strip())
ans = (n*m)>>1
cnt1,cnt2 = 0, 0
for i in range(n):
    for j in range(m):
        if a[i][j] == b[i][j]: cnt1+=1
        else: cnt2 += 1
if cnt2 <= ans:
    for i in range(n):
        for j in range(m):
            print(a[i][j],end = '')
        print()
else:
    for i in range(n):
        for j in range(m):
            if a[i][j] == '.': print('X',end = '')
            else: print('.',end = '')
        print()

D、Problem - D - Codeforces

题目大意是给我们两个人的初始位置和速度,再给我们整个轴的长度,让我们求最少需要多少时间才能让每个位置都至少有一个人走过。

这是官方题解原话,我们可以分几类来考虑这个问题:

1. 一个人把所有地方走完;

2. 两个人对穿,也就是说他们互相往另一个人的方向走,直到边界;

3. 两个人各负责自己的一边,然后在中间相遇,那么对于每个人,有两种选择,一种是先往端点走,一种是先往中间走,那么我们可以二分时间,就能够算出每个人往中间最多能走多少路,判断一下能不能把线段覆盖了就行啦!

前两点我们很好理解,主要说说最后一点:我们二分时间,然后计算两个人走的互不交叉并且各包含一个端点的最长路径,就是计算出时间T的情况下,p1和p2的两个人在自己那边能覆盖多少,两个覆盖的长度大于n就表示覆盖完了。

详细解析可以见下面两张图片:

接下来上ac的python3代码:

import sys

def solve():
    n,p1,v1,p2,v2 = map(float, sys.stdin.readline().split())
    if p1 > p2: p1,p2,v1,v2 = p2,p1,v2,v1
    #一人全走完
    ans = min((min(p1,n-p1) + n)/v1, (min(p2,n-p2) + n)/v2)
    #两人相向走直到边界
    ans = min(ans, max((n-p1)/v1, p2/v2))
    #两人各负责自己的一边,二分时间
    l,r,res = 0,1e9,0
    for i in range(200):
        t = (l+r)/2
        l1,l2 = v1*t,v2*t
        d1,d2 = max((l1+p1)/2, l1-p1), max((n-p2+l2)/2, l2-(n-p2))
        if d1 < p1: d1 = 0
        if d2 < n-p2: d2 = 0
        if d1 + d2 >= n: #时间多了
            res = t
            r = t
        else: l = t
    ans = min(res, ans)
    print(ans)

for _ in range(int(sys.stdin.readline())):
    solve()

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FarawayTraveler_Yuch

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值