蓝桥大赛官网校内模拟赛第一期

1、请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。请将这个数的十进制形式作为答案提交。

解析:

从2023开始递增寻找符合条件的数(因为题目要求找的数要大于2022)。

将每个数转换为十六进制并检查是否所有的字符都在A-F之间。

如果所有的字符都在A-F之间,那么这个数就是我们要找的数。

结果:2730

#  方法一
def find_min_hex_num():
    num = 2023
    while True:
        hex_num = hex(num)[2:].upper()  # 转换为十六进制并去掉前缀'0x'
        if all(c in 'ABCDEF' for c in hex_num):  # 检查是否所有字符都在A-F之间
            return num
        num += 1

print(find_min_hex_num())
#  方法二
def find_min_hex_num():
    num = 2023
    while True:
        hex_num = hex(num)[2:].upper()  # 转换为十六进制并去掉前缀'0x'
        is_valid = True
        for c in hex_num:  # 检查每个字符是否都在A-F之间
            if c not in 'ABCDEF':
                is_valid = False
                break
        if is_valid:
            return num
        num += 1

print(find_min_hex_num())

2、在 Excel 中,列的名称使用英文字母的组合。前 26 列用一个字母,依次为 A 到 Z,接下来 26*26 列使用两个字母的组合,依次为 AA 到 ZZ。请问第 2022 列的名称是什么

思路如下:首先,我们需要注意到,对于两位数的列名,它们的范围是从AA(相当于26+1)到ZZ(相当于26+26x26)。因此,如果要找的列号大于26且小于等于26+26*26,那么它将是一个两位数的列名。我们可以通过将列号减去26,然后进行整除和取余操作来得到两位数列名的两个字母。整除和取余的结果都可以通过查找字母表中的对应位置来得到相应的字母。注意,由于Excel列名是从1开始计数的,所以我们需要将整除和取余的结果减1。用两个字母表示:26+26*26=702 ,远小于2022

答案:BYT

def get_excel_column_name(n):
    letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    name = ''
    while n > 0:
        #  divmod()是Python的一个内置函数,用于同时计算两个数的商和余数。
        n, remainder = divmod(n - 1, 26)
        name = letters[remainder] + name
       
    return name

print(get_excel_column_name(2022))

3、对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 1900 年 1 月 1 日至 9999 年 12 月 31 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。

例如,2022年11月13日满足要求,因为 2+0+2+2=(1+1)+(1+3) 。请提交满足条件的日期的总数量。

思路:

    我们可以创建一个函数来计算一个数的各位数字之和。

    创建一个日期范围从1900年1月1日到9999年12月31日。

    对于每一天,我们将计算年、月、日的各位数字之和,并检查它们是否满足题目的条件。

    如果满足条件,我们就增加计数器的值。

答案: 70910

def digit_sum(n):
    return sum(int(digit) for digit in str(n))

def count_special_dates():
    count = 0
    for year in range(1900, 10000):
        for month in range(1, 13):
            for day in range(1, 32):
                if month in [4, 6, 9, 11] and day > 30:
                    continue
                elif month == 2 and day > 28:
                    if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
                        if day > 29:
                            continue
                    else:
                        continue
                if digit_sum(year) == digit_sum(month) + digit_sum(day):
                    count += 1
    return count

result = count_special_dates()
print("满足条件的日期总数量为:", result)
# 利用内置时间库

from datetime import datetime, timedelta

def digit_sum(n):
    return sum(int(digit) for digit in str(n))

def count_special_dates():
    start_date = datetime(1900, 1, 1)
    # 利用内置函数库计算式end需要设置为12月30日.
    end_date = datetime(9999, 12, 30)
    current_date = start_date
    count = 0
    while current_date <= end_date:
        year, month, day = current_date.year, current_date.month, current_date.day
        if digit_sum(year) == digit_sum(month) + digit_sum(day):
            count += 1
        current_date += timedelta(days=1)
    return count

result = count_special_dates()
print("满足条件的日期总数量为:", result)

4、小蓝有 30 个数,分别为:99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77 。小蓝可以在这些数中取出两个序号不同的数,共有 30*29/2=435 种取法。请问这 435 种取法中,有多少种取法取出的两个数的乘积大于等于 2022 。思路:

    遍历给定的30个数,取出第一个数a。

    对于每个a,再次遍历其后的数,取出第二个数b。

    计算a和b的乘积,如果大于等于2022,则满足条件,计数器加一

答案:189

def count_product_above_threshold(nums, threshold):
    count = 0
    for i in range(len(nums)):
        for j in range(i + 1, len(nums)):
            if nums[i] * nums[j] >= threshold:
                count += 1
    return count

nums = [99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77]
threshold = 2022
result = count_product_above_threshold(nums, threshold)
print("乘积大于等于2022的取法数量为:", result)
from itertools import combinations

# 给定的30个数
numbers = [99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77]
# 乘积大于等于2022的组合数量
count = 0
# 计算组合并统计满足条件的组合数量
for a, b in combinations(numbers, 2):
    if a * b >= 2022:
        count += 1

print("乘积大于等于2022的组合数量为:", count)

 5、小蓝有一个 30 行 60 列的数字矩阵,矩阵中的每个数都是 0 或 1 。如果从一个标为 1 的位置可以通过上下左右走到另一个标为 1 的位置,则称两个位置连通。与某一个标为 1 的位置连通的所有位置(包括自己)组成一个连通分块。请问矩阵中最大的连通分块有多大?

使用深度优先搜索(DFS)算法来解决。下面是一种可能的思路:

遍历整个矩阵,对于每个为 1 的位置,以该位置为起点进行深度优先搜索。

在深度优先搜索过程中,从当前位置开始,依次检查上、下、左、右四个方向的相邻位置,如果相邻位置也为 1,则继续递归深度优先搜索。

在深度优先搜索过程中,将已经访问过的位置标记为 0,避免重复访问。

统计每个连通分块的大小,并记录最大的连通分块大小。

答案:148

def maxConnectedBlock(matrix):
    def dfs(i, j):
        if i < 0 or i >= len(matrix) or j < 0 or j >= len(matrix[0]) or matrix[i][j] == 0:
            return 0
        matrix[i][j] = 0  # 标记为已访问
        size = 1
        size += dfs(i+1, j)
        size += dfs(i-1, j)
        size += dfs(i, j+1)
        size += dfs(i, j-1)
        return size

    maxBlockSize = 0
    for i in range(len(matrix)):
        for j in range(len(matrix[0])):
            if matrix[i][j] == 1:
                block_size = dfs(i, j)
                maxBlockSize = max(maxBlockSize, block_size)
    return maxBlockSize

import numpy as np

data = """
110010000011111110101001001001101010111011011011101001111110
010000000001010001101100000010010110001111100010101100011110
001011101000100011111111111010000010010101010111001000010100
101100001101011101101011011001000110111111010000000110110000
010101100100010000111000100111100110001110111101010011001011
010011011010011110111101111001001001010111110001101000100011
101001011000110100001101011000000110110110100100110111101011
101111000000101000111001100010110000100110001001000101011001
001110111010001011110000001111100001010101001110011010101110
001010101000110001011111001010111111100110000011011111101010
011111100011001110100101001011110011000101011000100111001011
011010001101011110011011111010111110010100101000110111010110
001110000111100100101110001011101010001100010111110111011011
111100001000001100010110101100111001001111100100110000001101
001110010000000111011110000011000010101000111000000110101101
100100011101011111001101001010011111110010111101000010000111
110010100110101100001101111101010011000110101100000110001010
110101101100001110000100010001001010100010110100100001000011
100100000100001101010101001101000101101000000101111110001010
101101011010101000111110110000110100000010011111111100110010
101111000100000100011000010001011111001010010001010110001010
001010001110101010000100010011101001010101101101010111100101
001111110000101100010111111100000100101010000001011101100001
101011110010000010010110000100001010011111100011011000110010
011110010100011101100101111101000001011100001011010001110011
000101000101000010010010110111000010101111001101100110011100
100011100110011111000110011001111100001110110111001001000111
111011000110001000110111011001011110010010010110101000011111
011110011110110110011011001011010000100100101010110000010011
010011110011100101010101111010001001001111101111101110011101
"""

matrix = np.array([list(map(int, line)) for line in data.split("\n") if line])

result = maxConnectedBlock(matrix)
print("最大连通分块的大小为:", result)

6、问题描述

  给定一天是一周中的哪天,请问 n 天后是一周中的哪天?

输入格式

  输入第一行包含一个整数 w,表示给定的天是一周中的哪天,w 为 1 到 6 分别表示周一到周六,w 为 7 表示周日。

  第二行包含一个整数 n。

输出格式

  输出一行包含一个整数,表示 n 天后是一周中的哪天,1 到 6 分别表示周一到周六,7 表示周日。

这是一个关于模运算的问题。我们知道,一周有7天,如果给定的天数超过了7,那么它就会从周一开始重新计数。因此,我们可以通过将给定的天数加上n,然后对7取模来得到n天后是一周中的哪一天。但是需要注意的是,如果结果为0,那么应该返回7,因为在这个问题中,我们是将周日表示为7而不是0。

答案:

#输入的w,n为6,10,输出为2

def which_day(w, n):

    return (w + n - 1) % 7 + 1



w = int(input("请输入给定的天是一周中的哪天(1-7):"))

n = int(input("请输入n的值:"))

result = which_day(w, n)

print(result)

7、问题描述

  小蓝负责一块区域的信号塔安装,整块区域是一个长方形区域,建立坐标轴后,西南角坐标为 (0, 0), 东南角坐标为 (W, 0), 西北角坐标为 (0, H), 东北角坐标为 (W, H)。其中 W, H 都是整数。他在 n 个位置设置了信号塔,每个信号塔可以覆盖以自己为圆心,半径为 R 的圆形(包括边缘)。为了对信号覆盖的情况进行检查,小蓝打算在区域内的所有横纵坐标为整数的点进行测试,检查信号状态。其中横坐标范围为 0 到 W,纵坐标范围为 0 到 H,总共测试 (W+1) * (H+1) 个点。给定信号塔的位置,请问这 (W+1)*(H+1) 个点中有多少个点被信号覆盖。

输入格式

        输入第一行包含四个整数 W, H, n, R,相邻整数之间使用一个空格分隔。接下来 n 行,每行包含两个整数 x, y,表示一个信号塔的坐标。信号塔可能重合,表示两个信号发射器装在了同一个位置。

输出格式

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

这是一个计算几何问题,可以使用欧几里得距离公式来判断每个点是否在信号塔的覆盖范围内。

首先,我们需要创建一个二维数组来表示整个区域,数组中的每个元素代表对应的点是否被信号覆盖。然后,我们遍历每个信号塔,对于每个信号塔,我们再遍历区域内的每个点,如果该点到信号塔的距离小于等于R,那么就将该点标记为被覆盖。最后,我们只需要统计被覆盖的点的数量即可.

'''
样例输入:
    10 10 2 5
    0 0
    7 0
'''

def count_covered_points(W, H, towers, R):
    # 创建一个二维数组表示整个区域
    area = [[0 for _ in range(W+1)] for _ in range(H+1)]
    
    # 遍历每个信号塔
    for x, y in towers:
        # 遍历区域内的每个点
        for i in range(W+1):
            for j in range(H+1):
                # 如果该点到信号塔的距离小于等于R,就将该点标记为被覆盖
                if (x-i)**2 + (y-j)**2 <= R**2:
                    area[j][i] = 1
    
    # 统计被覆盖的点的数量
    return sum(sum(row) for row in area)


# 输入数据
W, H, n, R = map(int, input().split())
towers = [list(map(int, input().split())) for _ in range(n)]

# 输出结果
print(count_covered_points(W, H, towers, R))

8、问题描述

  小蓝有一个 n * m 大小的矩形水域,小蓝将这个水域划分为 n 行 m 列,行数从 1 到 n 标号,列数从 1 到 m 标号。每行和每列的宽度都是单位 1 。现在,这个水域长满了水草,小蓝要清理水草。每次,小蓝可以清理一块矩形的区域,从第 r1 行(含)到第 r2 行(含)的第 c1 列(含)到 c2 列(含)。经过一段时间清理后,请问还有多少地方没有被清理过。

输入格式

  输入第一行包含两个整数 n, m,用一个空格分隔。第二行包含一个整数 t ,表示清理的次数。接下来 t 行,每行四个整数 r1, c1, r2, c2,相邻整数之间用一个空格分隔,表示一次清理。请注意输入的顺序。

输出格式

  输出一行包含一个整数,表示没有被清理过的面积。

这个问题的关键在于如何有效地记录和更新每次清理操作后的水域状态。一个直观的方法就是使用一个二维数组来表示整个水域,数组中的每个元素代表对应的区域是否被清理过。初始化:我们首先创建一个大小为 n*m 的二维数组,初始时每个元素都为 1,表示对应的区域还没有被清理过。清理操作:对于每次清理,我们就将对应的区域内的元素都设置为 0,表示已经被清理过了。注意到,因为行列的索引是从 1 开始的,而 Python 的列表索引是从 0 开始的,所以在进行清理操作时,需要将行列的索引减 1。计算结果:最后,我们只需要统计数组中值为 1 的元素的数量,就得到了没有被清理过的面积。

'''
样例输入
2 3
2
1 1 1 3
1 2 2 2

'''

def clean_area(n, m, cleanings):
    # 创建一个二维数组表示整个水域
    area = [[1 for _ in range(m)] for _ in range(n)]
    
    # 遍历每次清理
    for r1, c1, r2, c2 in cleanings:
        # 将对应的区域内的元素都设置为 0
        for i in range(r1-1, r2):
            for j in range(c1-1, c2):
                area[i][j] = 0
    
    # 统计数组中值为 1 的元素的数量
    return sum(sum(row) for row in area)


# 输入数据
n, m = map(int, input().split())
t = int(input())
cleanings = [list(map(int, input().split())) for _ in range(t)]

# 输出结果
print(clean_area(n, m, cleanings))

9、问题描述

  小蓝准备在一个空旷的场地里面滑行,这个场地的高度不一,小蓝用一个 n 行 m 列的矩阵来表示场地,矩阵中的数值表示场地的高度。

  如果小蓝在某个位置,而他上、下、左、右中有一个位置的高度(严格)低于当前的高度,小蓝就可以滑过去,滑动距离为 1 。

  如果小蓝在某个位置,而他上、下、左、右中所有位置的高度都大于等于当前的高度,小蓝的滑行就结束了。

  小蓝不能滑出矩阵所表示的场地。

  小蓝可以任意选择一个位置开始滑行,请问小蓝最多能滑行多远距离。

这是一个典型的深度优先搜索(DFS)问题。我们需要找出从每一个位置开始,最多能滑行的距离。对于每个位置,我们都尝试向上、下、左、右四个方向滑行,如果滑行的方向的高度低于当前位置的高度,那么就继续滑行,否则就停止滑行。

初始值为1是因为我们在计算滑行距离时,需要包括开始滑行的这个位置。即使小蓝在这个位置上不能向任何方向滑行,他仍然在这个位置上"滑行"了一次。所以,即使小蓝不能从当前位置滑行到任何其他位置,滑行距离也至少为1。在深度优先搜索中,我们遍历每个位置,尝试向四个方向滑行。如果可以滑行到某个位置,我们就递归调用深度优先搜索函数,并将滑行距离加1。如果不能滑行到任何位置,我们就返回当前的滑行距离,即1。

'''
样例输入
4 5
1 4 6 3 1
11 8 7 3 1
9 4 5 2 1
1 3 2 2 1
'''
def max_slide_distance(n, m, heights):
    # 初始化滑行距离数组
    slide_distances = [[-1 for _ in range(m)] for _ in range(n)]
    
    # 定义四个方向
    directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
    
    # 定义深度优先搜索函数
    def dfs(i, j):
        if slide_distances[i][j] != -1:
            return slide_distances[i][j]
        
        max_distance = 1
        for dx, dy in directions:
            x, y = i + dx, j + dy
            if 0 <= x < n and 0 <= y < m and heights[x][y] < heights[i][j]:
                max_distance = max(max_distance, dfs(x, y) + 1)
        
        slide_distances[i][j] = max_distance
        return max_distance
    
    # 对每个位置进行深度优先搜索
    for i in range(n):
        for j in range(m):
            dfs(i, j)
    
    # 返回最大的滑行距离
    return max(max(row) for row in slide_distances)


# 输入数据
n, m = map(int, input().split())
heights = [list(map(int, input().split())) for _ in range(n)]

# 输出结果
print(max_slide_distance(n, m, heights))

10、问题描述

  小蓝有一个序列 a[1], a[2], ..., a[n]。

  给定一个正整数 k,请问对于每一个 1 到 n 之间的序号 i,a[i-k], a[i-k+1], ..., a[i+k] 这 2k+1 个数中的最小值是多少?当某个下标超过 1 到 n 的范围时,数不存在,求最小值时只取存在的那些值。

遍历数组 a 的每个元素,设当前元素的下标为 i。

初始化一个变量 min_val,用来保存当前位置 i 的最小值,初始化为正无穷大。

对于当前位置 i,从 i-k 到 i+k 的范围内遍历,找到其中的最小值。

将找到的最小值与 min_val 进行比较,更新 min_val。

将 min_val 添加到结果数组中。

完成遍历后,输出结果数组

''' 
样例输入
5
5 2 7 4 3
1
'''

n = int(input())
a = list(map(int, input().split()))
k = int(input())

def find_num(n, a, k):
    res = []
    for i in range(n):
        min_val = float('inf')
        for j in range(max(0, i - k), min(n, i + k + 1)):
            min_val = min(min_val, a[j])
        res.append(min_val)
    return res

result = find_num(n, a, k)

for i in result:
    print(i, end=' ')

11、一个数的数位和是指这个数各个数位上的数字之和。例如 2023 的数位和是 2+0+2+3=7 。对于以下这些数(8行,每行8个,共64个),请问数位和最小的数是多少?(如果有多个,请回答出现最早的那个)

答案:223321

def digit_sum(number):
    return sum(int(digit)for digit in str(number))

# 输入所有数字
numbers = [
    454771, 329157, 801601, 580793,
    755604, 931703, 529875, 361797,
    604358, 529564, 574776, 821517,
    195563, 688516, 223321, 607845,
    284772, 603562, 543328, 707484,
    533688, 380468, 233733, 257995,
    896582, 670074, 912386, 702393,
    722092, 834842, 126346, 606526,
    376981, 910643, 413754, 945725,
    817853, 651778, 350775, 676550,
    316935, 487808, 939526, 900568,
    423326, 298936, 927671, 539773,
    136326, 717022, 886675, 466684,
    436470, 558644, 267231, 902422,
    743580, 857864, 529622, 320921,
    595409, 486860, 951114, 558787
]

# 计算每个数字的数位和
digit_sums = [digit_sum(num) for num in numbers]

# 找到数位和最小的数
min_digit_sum = min(digit_sums)

# 找到第一个具有最小数位和的数字
min_number = numbers[digit_sums.index(min_digit_sum)]

# 输出结果
print(min_number)

 12、小蓝有一根长度为 L 的绳子,每对折一次,长度变为原来的一半,请问对折多少次后长度不超过 1 。例如,当 L=6 时,对折一次长度为 3,对折两次长度为 1.5 ,对折 3 次长度为 0.75,所以 3 次后长度不超过 1 。

def find_folding_times(length):
    n = 0
    while length > 1:
        length /= 2
        n += 1
    return n

L =int(input("输入绳子长度:")) # 6
folding_times = find_folding_times(L)
print(f"对折 {folding_times} 次后,长度不超过 1。")

13、问题描述

  给定一个由大写字母组成的长度为 n 的字符串,请在字符串中删除 m 个字符,使得剩下的字符串的字典序最小。

输入格式

  输入的第一行包含两个整数 n, m ,用一个空格分隔。

  第二行包含一个长度为 n 的字符串。

输出格式

  输出一行包含一个长为 n-m 的字符串,表示答案。

思路:

创建一个空列表 result 用于存储最终的结果。

遍历输入的字符串 s 中的每个字符 char。

对于每个字符 char,如果 result 非空且还有删除次数 m 且列表末尾的字符大于当前字符 char,则弹出列表末尾的字符,直到满足条件。

将当前字符 char 添加到 result 列表中。

当遍历结束后,如果还有剩余的删除次数 m,则从 result 列表中弹出字符直到删除次数用完。

最后,将 result 列表中的字符连接起来,即为所求结果。

def delete_chars(n, m, s):
    result = []
    for char in s:
        while m > 0 and result and result[-1] > char:
            result.pop()
            m -= 1
        result.append(char)
    return ''.join(result[:n - m])

# 示例输入
n, m = map(int, input().split())
s = str(input())
result = delete_chars(n, m, s)
print(result)

答案仅供参考

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值