栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

蓝桥杯【第13届省赛】Python

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

蓝桥杯【第13届省赛】Python

C语言网:2022年蓝桥杯第十三届大赛省赛真题https://www.dotcpp.com/oj/train/1035/

 这个题集涵盖了第十三届省赛所有组别的编程题,但 Python B 组的题解我写在了另一篇文章中:蓝桥杯【第13届省赛】Python B组 91.75分

刷题统计  100

【题目描述】

        小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a 道题目,周六和周日每天做 b 道题目。请你帮小明计算,按照计划他将在第几天实现做题数大于等于 n 题?

【输入格式】

        输入一行包含三个整数 a, b 和 n

【输出格式】

        输出一个整数代表天数。

【样例】

输入输出
10 20 998

【评测用例规模与约定】

50%
100%

【解析及代码】 

from math import ceil

a, b, n = map(int, input().split())

# 每周做题数
num_per_week = 5 * a + 2 * b
# 花费周数
cost_week = n // num_per_week

# 经过 m 周后还差多少
undone = n - cost_week * num_per_week
# 总共花费天数
cost_day = cost_week * 7

if undone <= 5 * a:
    cost_day += ceil(undone / a)
else:
    undone -= 5 * a
    cost_day += 5 + ceil(undone / b)

print(cost_day)

修剪灌木

【题目描述】

        爱丽丝要完成一项修剪灌木的工作。有 N 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晚会修剪一棵灌木,让灌木的高度变为 0 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始,每天向右修剪一棵灌木。当修剪了最右侧的灌木后,她会调转方向,下一天开始向左修剪灌木。直到修剪了最左的灌木后再次调转方向。然后如此循环往复。灌木每天从早上到傍晚会长高 1 厘米,而其余时间不会长高。在第一天的早晨,所有灌木的高度都是 0 厘米。爱丽丝想知道每棵灌木最高长到多高。

【输入格式】

        一个正整数 N ,含义如题面所述。

【输出格式】

        输出 N 行,每行一个整数,第行表示从左到右第 i 棵树最高能长到多高。

【样例】

输入输出
3

4

2

4

【评测用例规模与约定】

30%
100%

【解析及代码】

分析一下样例,当输入 3 时输出是 4, 2, 4

早晨1 1 11 2 22 1 33 1 14 1 2
傍晚0 1 11 0 22 1 03 0 10 1 2

从表中可以看到:灌木最高高度 = 裁剪时间间隔 + 1

但还要考虑一种情况:灌木在第一次裁剪之前就已经达到最高高度

矩形拼接  100

【题目描述】

        已知 3 个矩形的大小依次是 a1 × b1, a2 × b2 和 a3 × b3。用这 3 个矩形能拼出的所有多边形中,边数最少可以是多少?例如用 3 × 2 的矩形(用 A 表示)、4 × 1 的矩形(用 B 表示)和 2 × 4 的矩形(用 C 表示)可以拼出如下 4 边形

​

        例如用 3 × 2 的矩形(用 A 表示)、3 × 1 的矩形(用 B 表示)和 1 × 1 的矩形(用 C 表示)可以拼出如下 6 边形。

​

【输入格式】

        输入包含多组数据。

        第一行包含一个整数 T,代表数据组数。

        以下 T 行,每行包含 6 个整数 a1, b1, a2, b2, a3, b3,其中 a1, b1 是第一个矩形的边长,a2, b2 是第二个矩形的边长,a3, b3 是第三个矩形的边长。

【输出格式】

        对于每组数据,输出一个整数代表答案。

【样例】

输入输出
2
2 3 4 1 2 4
1 2 3 4 5 6

4

6

【评测用例规模与约定】

10%​
30%​
60%​
100%​

【解析及代码】

小的不才,没有什么比较好的解法,解法接近暴力,基本的思路是:

  • 将三个矩形分成 2 + 1 的形式,对前两个矩形进行拼接,以 int 表示凸边,以自定义类 Corner 表示凹角
  • 使用列表存储凸边、凹角,以表示多边形,该多边形的边数为:​
class Corner:
    ''' 凹角'''

    def __init__(self, edge: list, third: list):
        # 该凹角相邻的两条边
        self.edge = edge
        # 该凹角在拼接上第三个矩形后, 对边数的贡献
        self.contri = self.stack(third) + 2

    def stack(self, rect):
        # 刚好可以嵌入转角
        for r in rect, rect[::-1]:
            if r == self.edge:
                return -2
        # 有一条边与转角吻合
        for a in rect:
            for b in self.edge:
                if a == b:
                    return 0
        # 无最佳拼接方法
        return 2
  • 当第三个矩形拼接在凹角处时,使用 stack 方法计算该凹角对边数的贡献
  • 当第三个矩形未拼接在凹角处时,则凹角对边数的贡献是 2
groups = int(input())
for _ in range(groups):
    # 整理出矩形的边长
    rects = list(map(int, input().split()))
    rects = [rects[i * 2: (i + 1) * 2] for i in range(3)] * 2
    # 对每个二元组进行拼接: 凸边, 凹角
    result = []
    for i in range(3):
        temp1, temp2, temp3 = rects[i: i + 3]
        for a in range(2):
            for b in range(2):
                # 新多边形
                new = [temp1[a], temp2[b], temp1[1 - a] + temp2[1 - b]]
                have_corner = temp1[a] != temp2[b]
                # 两拼接边长不相等: 产生转角
                if have_corner:
                    # 拼接残差
                    res = abs(temp1[a] - temp2[b])
                    if temp1[a] > temp2[b]:
                        corner = Corner([res, temp2[1 - b]], temp3)
                        new += [temp1[1 - a], corner]
                    else:
                        corner = Corner([res, temp1[1 - a]], temp3)
                        new += [temp2[1 - b], corner]
                # 两拼接边长相等
                else:
                    new += [temp1[1 - a] + temp2[1 - b]]
                # 拼接第三个矩形
                basic_num = len(new) + have_corner
                for ele in set(new):
                    # 在转角处拼接: 访问 Corner 的 contri 属性
                    if isinstance(ele, Corner):
                        result += [len(new) - 1 + ele.contri]
                    # 非转角处拼接: Corner 对边数的贡献是 2
                    else:
                        for c in set(temp3):
                            if c == ele:
                                result += [basic_num]
                                break
                            result += [basic_num + 2]
    print(min(result))

GCD  100

【题目描述】

        给定两个不同的正整数 a, b,求一个正整数 k 使得 gcd(a + k, b + k) 尽可能大,其中 gcd(a, b) 表示 a 和 b 的最大公约数,如果存在多个 k,请输出所有满足条件的 k 中最小的那个。

【输入格式】

        输入一行包含两个正整数 a, b,用一个空格分隔。

【输出格式】

        输出一行包含一个正整数 k。

【样例】

输入输出
5 71

【评测用例规模与约定】

20%​
40%​
100%

【解析及代码】

两个数的最大公约数只可能是两者之差的因数,即 gcd(a + k, b + k) 最大为 |a - b|,记为 gain:

​

求 k 使 m, n 均为整数,有 ​

为使 k 尽可能小,令 ​

from fractions import Fraction
from math import ceil

a, b = map(int, input().split())
max_gcd = abs(a - b)

gain = Fraction(a, max_gcd)
k = ceil(gain) * max_gcd - a

print(int(round(k)))

这种题容易因为小数精度的问题丢分,使用分数可以保证精度

重新排序  5

【问题描述】

        给定一个数组 A 和一些查询 Li , Ri,求数组中第 Li 至第 Ri 个元素之和。

        小蓝觉得这个问题很无聊,于是他想重新排列一下数组,使得最终每个查询结果的和尽可能地大。小蓝想知道相比原数组,所有查询结果的总和最多可以增加多少?

【输入格式】

        输入第一行包含一个整数 n。

        第二行包含 n 个整数 A1, A2, · · · , An,相邻两个整数之间用一个空格分隔。

        第三行包含一个整数 m 表示查询的数目。

        接下来 m 行,每行包含两个整数 Li、Ri ,相邻两个整数之间用一个空格分隔。

【输出格式】

        输出一行包含一个整数表示答案。

【样例】

输入输出说明
5
1 2 3 4 5
2
1 3
2 5
4

原来的和为 6 + 14 = 20,

重新排列为 (1, 4, 5, 2, 3)

后和为 10 + 14 = 24,增加了 4。

【评测用例规模与约定】

30%​
50%​
70%​
100%​

【解析及代码】

使用权重向量来记录数列对应位置的数被取的次数

为了降低时间复杂度,使用差分数列进行表示

对权重向量、原数列进行排序,按序相乘即为最优结果

length = int(input())
seq = list(map(int, input().split()))
# 权重向量的差分数列
weight = [0] * length

for _ in range(int(input())):
    left, right = map(lambda i: int(i) - 1, input().split())
    # 更新差分数列
    weight[left] += 1
    if right + 1 < length:
        weight[right + 1] -= 1

# 还原得到权重向量
for i in range(1, length):
    weight[i] += weight[i - 1]

origin = [e * w for e, w in zip(seq, weight)]
current = [e * w for e, w in zip(*map(sorted, [seq, weight]))]
print(sum(current) - sum(origin))

我觉得思路应该没错,但是在 C 语言网的得分只有 5 分……

青蛙过河

【问题描述】

        小青蛙住在一条河边,它想到河对岸的学校去学习。小青蛙打算经过河里的石头跳到对岸。

        河里的石头排成了一条直线,小青蛙每次跳跃必须落在一块石头或者岸上。不过,每块石头有一个高度,每次小青蛙从一块石头起跳,这块石头的高度就会下降 1,当石头的高度下降到 0 时小青蛙不能再跳到这块石头上(某次跳跃后使石头高度下降到 0 是允许的)。

        小青蛙一共需要去学校上 x 天课,所以它需要往返 2x 次。当小青蛙具有一个跳跃能力 y 时,它能跳不超过 y 的距离。

        请问小青蛙的跳跃能力至少是多少才能用这些石头上完 x 次课。

【输入格式】

        输入的第一行包含两个整数 n, x,分别表示河的宽度和小青蛙需要去学校的天数。请注意 2x 才是实际过河的次数。

        第二行包含 n − 1 个非负整数 H1, H2, · · · , Hn-1,其中 Hi > 0 表示在河中与小青蛙的家相距 i 的地方有一块高度为 Hi 的石头,Hi = 0 表示这个位置没有石头。

【输出格式】

        输出一行,包含一个整数,表示小青蛙需要的最低跳跃能力。

【样例】

输入输出说明
5 1
1 0 1 0
4

由于只有两块高度为 1 的石头,所以往返只能各用一块。

第 1 块石头和对岸的距离为 4,如果小青蛙的跳跃能力为 3

则无法满足要求。所以小青蛙最少需要 4 的跳跃能力。 

【评测用例规模与约定】

30%​
60%​
100%​

【解析及代码】

 质因数个数  71

【题目描述】

        给定正整数 n,请问有多少个质数是 n 的约数。

【输入格式】

        输入的第一行包含一个整数 n。

【输出格式】

        输出一个整数,表示 n 的质数约数个数。

【样例】

输入输出
3963

【评测用例规模与约定】

30%
60%
100%

【解析及代码】 

def factorization(n):
    ''' 质因数分解'''
    factor = []
    i = 2
    while i ** 2 <= n:
        if n % i == 0:
            factor.append(i)
            n //= i
            while n % i == 0:
                n //= i
        i += 1
    if i > 1:
        factor.append(i)
    return factor


n = int(input())
print(len(factorization(n)))

时间超限,刷不动了

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/947247.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号