蓝桥杯题解|2019|Python版

本文提供了2019年第十届蓝桥杯C/C++省赛B组的详细题解,涵盖从组队问题到后缀表达式的各类算法挑战,通过具体代码示例解析每道题目,帮助读者深入理解算法设计与实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2019 第十届蓝桥杯C/C++ 省赛B组题解

1. 试题 A: 组队

可以考虑使用 Excel 进行辅助计算。


答案:490

2. 试题 B: 年号字串

特殊的进制转换——十进制转二十六进制

27%26=1……1(即 AA)
28%26=1……2(即 AB)
329%26=12……17(即 LQ)
2019%26=77……17,又 77%26= 2……25(即 BYQ)

答案:BYQ

3. 试题 C: 数列求值

# 不能采用递归的方法,会爆栈
n = int(input())
d = 0

a=b=c=1
if n == 1 or n == 2 or n == 3:
    d = 1
else:
    for i in range(4, n+1):
        d = (a+b+c)%10000
        a, b, c = b%10000, c%10000, d%10000 


print(d)
# output: 4659

4. 试题 D: 数的分解

n=2019

def fun(t):
    # 判断是否包含 2 和 4。
    if '2' in str(t) or '4' in str(t):
        return True
    else:
        return False

result = []

for i in range(1, n+1):
    if fun(i):
        # 如果包含数字,则退出本层循环。
        continue
    for j in range(1, n+1):
        if fun(j):
            continue
        k = n - i - j
        if fun(k) or k<=0:
            # 注意 k 可能为负数。 
            continue
        if i == j or j == k or i == k:
            continue
        result.append(
                       tuple( 
                                sorted([i, j, k])
                            )
                    )
        # 保存所有满足情况的条件。
        # 注意 Python 中的 list 无法使用 set 去重。


print(len(set(result)))
# 使用 set 函数去重复,使用 len 求得方法的个数。

# output: 40785

5. 试题 E: 迷宫

from pprint import pprint
from queue import Queue
# queue 是 Python 自带的库。

string = '''010000
000100
001001
110000'''

string_list = string.split('\n')
cols = len(string_list[0])
rows = len(string_list)
# 求迷宫的行数和列数

for i in range(len(string_list)):
    string_list[i] = '1' + string_list[i] + '1'
string_list = [(cols+2)*'1'] + string_list + [(cols+2)*'1']
visited = [list(map(int, list(i))) for i in string_list]
# 为迷宫加上边界。

x_dire = [0, 1, 0, -1]
y_dire = [1, 0, -1, 0]
# 初始化方向数组

prev = [[(-1, -1)]*(cols+2) for i in range(rows+2)]
# 用于保存前一个节点

visited[1][1] = 1
que = Queue()
que.put((1,1))
# 以(0,0)为起点开始移动


while que.qsize() != 0:
    node = que.get()
    for i in range(4):
        x = node[0] + x_dire[i]
        y = node[1] + y_dire[i]
        if visited[x][y] != 1:
            visited[x][y] = 1
            prev[x][y] = (node[0], node[1])
            que.put((x, y))
# 找出前一个点的位置

route = []
def printf(node):
    if node == (-1,-1):
        return
    route.append(node)
    printf(prev[node[0]][node[1]])
printf((rows, cols))
# 找出完整的路线

dire = {0:'R', 1:'D', 2:'L', 3:'U'}
result = ''
while len(route) != 1:
    a = route.pop()
    b = route[-1]
    for i in range(4):
        x = a[0] + x_dire[i]
        y = a[1] + y_dire[i]
        if (x, y) == b:
            result += dire[i]

print(result)
# output: DRRURRDDDR

6. 试题 F: 特别数的和

n = int(input())

temp = []
for i in range(n+1):
    string = str(i)
    if '2' in string or '0' in string or '1' in string or '9' in string:
        temp.append(i)
result = sum(temp)

print(result)
# input: 40

7. 试题 G: 完全二叉树的权值

import math

n = int(input())
nums = list(map(int, input().split()))

h = int(math.log(n+1, 2))
# 求解二叉树的高度。

ss = []
for i in range(h):
    s = 0
    for j in range(2**i, 2**(i+1)):
        k = j-1
        s += nums[k]
    ss.append(s)
# 对每个深度的权值进行相加。

max_s = max(ss)
max_h = -1
for i in range(len(ss)):
    if max_s == ss[i]:
        max_h = i + 1
print(max_h)
# 找到权值最高的深度

# input:7
# 1 6 5 4 3 2 1
# output:2

8. 试题 H: 等差数列

n = int(input())
nums = list(map(int, input().split()))

nums.sort()
k = 100000
# 对列表进行排序

plist = [nums[i] - nums[i-1] for i in range(1, n)]
# 求解列表的差值

def fun(a, b):
    while b != 0:
        a, b = b, a%b
    return a
# 求解最小公倍数函数

minq = 1000000
for i in range(1, len(plist)):
    q = fun(plist[i-1], plist[i])
    if q < minq:
        minq = q
# 找到所有差值中的最小公倍数

res = 1
minn = min(nums)
maxn = max(nums)
while minn != maxn:
    minn += minq
    res += 1
# 求解数列中数字的个数

if 0 in plist:
    res = n
# 当公差为 0 时,数列中数字的个数为当前数字的个数。

print(res)

# input: 5
# 2 6 4 10 20
# output: 20

9. 试题 I: 后缀表达式

n, m = list(map(int, input().split()))
nums = list(map(int, input().split()))
abs_nums = list(map(abs, nums))

result = 0
s = sum(abs_nums)

if m == 0:
    result = s
else:
    if min(nums) > 0:
        result = s - min(abs_nums) * 2
    else:
        result = s 

print(result)
# input: 5 5
# 1 -2 -3 -4 5 -6 -7 -8 -9 -10 -11
# output: 66

参考教程:https://blog.csdn.net/weixin_43302818/article/details/88805530

10. 试题 J: 灵能传输

不会(

### 蓝桥杯巧克力问题解析 #### 问题描述 蓝桥杯竞赛中的“分巧克力”问题是经典的算法优化类题目。该问题的核心在于如何通过合理的切割方式,使得从已有的 $N$ 块矩形巧克力中切出尽可能大的正方形巧克力块,并满足总数达到指定的 $K$ 块。 --- #### 解决思路 此问题可以通过 **二分查找法** 来解决。具体来说: 1. 定义一个 `check` 函数用于验证当前假设的最大边长是否能够满足至少分割出 $K$ 块巧克力的要求。 2. 使用二分查找来逐步缩小可能的最大边长范围,直到找到最优解为止。 以下是详细的 Python 实现代码及其解释[^4]。 --- #### Python 实现代码 ```python import os import sys def check(a): """检查能否切出至少k块大小为a*a的巧克力""" num = 0 # 统计能切出多少块符合条件的巧克力 for h, w in chocolates: # 遍历每一块原始巧克力 num += (h // a) * (w // a) # 当前巧克力可切出的数量 if num >= k: return True # 如果总数量大于等于k,则可行 return False n, k = map(int, input().split()) # 输入巧克力块数和目标块数 chocolates = [list(map(int, input().split())) for _ in range(n)] # 输入每块巧克力的高度和宽度 # 初始化二分查找边界 left, right = 1, 100000 # 边界可以根据实际情况调整 while left < right: mid = (left + right) // 2 # 取中间值作为试探边长 if check(mid): # 若mid可行,则尝试更大的边长 left = mid + 1 else: # 否则减小边长 right = mid print(left - 1) # 输出最大可能的边长 ``` --- #### 代码详解 1. **输入处理** - 用户需先输入两个整数 $N$ 和 $K$,分别表示巧克力块数以及需要切出的目标块数。 - 接下来会读取 $N$ 行数据,每一行代表一块巧克力的高度和宽度。 2. **核心逻辑** - 利用 `check` 函数判断某一边长是否能满足条件。对于每一块巧克力 $(h, w)$,计算其最多可以切成 $\text{floor}(h/a) \times \text{floor}(w/a)$ 块大小为 $a \times a$ 的子巧克力。 - 结合二分查找不断逼近最终答案,确保效率最大化。 3. **输出结果** - 最终打印的结果即为所能切出的最大正方形巧克力边长。 --- #### 注意事项 - 数据规模较大时需要注意性能优化,因此采用二分查找而非暴力枚举方法。 - 边界的设定应合理,通常可根据题目约束设置上下限(如上述代码中的 `[1, 100000]`)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值