一力破万法系列之暴力解决第十五届蓝桥杯省赛python组一:

前言

本系列遵循大道至简的核心思想,旨在利用返璞归真的暴力法来解决历届蓝桥杯中所出现过的真题。

1.穿越时空之门

问题描述

随着 2024 年的钟声回荡,传说中的时空之门再次敞开。这扇门是一条神秘的通道,它连接着二进制和四进制两个不同的数码领域,等待着勇者们的探索。

在二进制的领域里,勇者的力量被转换成了力量数值的二进制表示中各数位之和。

在四进制的领域里,力量的转换规则相似,变成了力量数值的四进制表示中各数位之和。

穿越这扇时空之门的条件是严苛的:当且仅当勇者在二进制领域的力量等同于四进制领域的力量时,他才能够成功地穿越。

国王选定了小蓝作为领路人,带领着力量值从 1到 2024 的勇者们踏上了这段探索未知的旅程。作为小蓝的助手,你的任务是帮助小蓝计算出,在这 2024 位勇者中,有多少人符合穿越时空之门的条件。

答案提交

这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

解题思路

这道题作为第十五届蓝桥杯的第一题(开胃菜)来说可以说没有任何的难度,根据题意我们只需要把从1到2024的所有十进制数字首先分别转化成二进制数字和四进制数字,如果转化成的二进制数字之和正好等于转化成的四进制数字之和则符合题意。

代码部分

# 十进制转二进制
def tran_two(x):
    ans = 0
    while x >= 2:
        temp = x % 2
        x = x // 2
        ans += temp
    ans += x
    return ans


# 十进制转四进制
def tran_four(x):
    ans = 0
    while x >= 4:
        temp = x % 4
        x = x // 4
        ans += temp
    ans += x
    return ans


# 判断是否符合条件并计算个数
num = 0
for i in range(1, 2025):
    ans1 = tran_two(i)
    ans2 = tran_four(i)
    if ans1 == ans2:
        num += 1
print(num)

2.数字串个数

问题描述

小蓝想要构造出一个长度为10000 的数字字符串,有以下要求:

  1. 小蓝不喜欢数字 0,所以数字字符串中不可以出现 0;

  2. 小蓝喜欢数字 3和 7,所以数字字符串中必须要有 3 和 7 这两个数字。 

请问满足题意的数字字符串有多少个?这个数字会很大,你只需要输出其对 10^{9}+7 取余后的结果。

答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

解题思路

这道题本身也并没什么难度,但他的难点在于如何去表示这个结果,就像我第一眼看到这道题就想用组合来做,但发现很难去表示,最后发现可以使用间接法来进行转化表示,具体如何转换的大家一看代码便清楚了。

代码部分

x = 9 ** 10000 - 2 * 8 ** 10000 + 7 ** 10000
ans = x % (10 ** 9 + 7)
print(ans)

3.连连看

问题描述

小蓝正在和朋友们玩一种新的连连看游戏。在一个 n×m 的矩形网格中,每个格子中都有一个整数,第 i 行第 j 列上的整数为 A_{i, j}。玩家需要在这个网格中寻找一对格子 (a,b)−(c,d) 使得这两个格子中的整数 A_{a,b}​ 和 A_{c,d}​ 相等,且它们的位置满足 ∣a−c∣=∣b−d∣>0 。请问在这个 n×m 的矩形网格中有多少对这样的格子满足条件。

输入格式

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

接下来 n行,第 i 行包含 m 个正整数 A_{i,1}A_{i,2},⋯,A_{i,m},相邻整数之间使用一个空格分隔。

输出格式

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

解题思路

从这道题开始,蓝桥杯才开始真正的上难度。这道题我使用的方式我叫做矩阵变量法,将输入的数据用矩阵表示,(这里为方便描述,A_{i,j}我姑且描述为(i, j))经过分析不难发现本题所满足的条件有四种情况,即(a,b)和(c,d)之间的关系应该满足1.(a,b)=(c+x,d+x)2.(a,b)=(c+x,d-x)3.(a,b)=(c-x,d+x)4.(a,b)=(c-x,d-x)四种中的一者即可,我这里制造了一个变量x巧妙地实现了对条件的遍历,具体细节请看代码。

代码部分

# 读取矩阵大小信息
infos = input().split()
row = int(infos[0])
col = int(infos[1])
# 构建相应大小的全0矩阵
matrix = [[0 for j in range(col)] for i in range(row)]
# 构建题目所述矩阵
for i in range(row):
  info = input().split()
  for j in range(col):
    matrix[i][j] = int(info[j])
# 条件+计数
cnt = 0
for i in range(row):
  for j in range(col):
    for x in range(1, max(row, col)):
      if (i+x < row) and (j+x < col) and matrix[i][j] == matrix[i+x][j+x]:
        cnt += 1
      if (i+x < row) and (j-x >= 0) and matrix[i][j] == matrix[i+x][j-x]:
        cnt += 1
      if (i-x >= 0) and (j+x < col) and matrix[i][j] == matrix[i-x][j+x]:
        cnt += 1
      if (i-x >= 0) and (j-x >= 0) and matrix[i][j] == matrix[i-x][j-x]:
        cnt += 1
print(cnt)

4.神奇闹钟

问题描述

小蓝发现了一个神奇的闹钟,从纪元时间(1970 年 1 月 1 日 00:00:00)开始,每经过 x 分钟,这个闹钟便会触发一次闹铃 (纪元时间也会响铃)。这引起了小蓝的兴趣,他想要好好研究下这个闹钟。

对于给出的任意一个格式为 уууу-MM-dd   HH:mm:ss 的时间,小蓝想要知道在这个时间点之前 (包含这个时间点) 的最近的一次闹铃时间是哪个时间?

注意,你不必考虑时区问题。

输入格式

输入的第一行包含一个整数 T,表示每次输入包含 T 组数据。

接下来依次描述 T 组数据。

每组数据一行,包含一个时间(格式为 уууу-MM-dd  HH:mm:ss)和一个整数 x,其中 x 表示闹铃时间间隔(单位为分钟)。

输出格式

输出 T 行,每行包含一个时间(格式为 уууу-MM-dd  HH:mm:ss),依次表示每组数据的答案。

解题思路

这套题的思路其实蛮简单的,就是算出题目所给时间和纪元时间的时间差,再整除时间间隔x获得最小整数倍数n,再用纪元时间+n*x(时间间隔)就能获得所求,关键点在于运用datetime模块来表示时间,具体请看代码。

代码部分

import datetime
batch_size = int(input())
start_time = datetime.datetime(1970, 1, 1, 0, 0, 0)
results = []
for i in range(batch_size):
    infos = input().split()
    gap_time = int(infos[2])
    my_time = datetime.datetime.strptime(infos[0]+' '+infos[1], '%Y-%m-%d %H:%M:%S')
    delta_time = my_time - start_time
    # 创建gap_time分钟的时间间隔
    time_delta = datetime.timedelta(minutes=gap_time)
    # 间隔的时间整除时间间隔
    n = delta_time // time_delta
    result = start_time + n * datetime.timedelta(minutes=gap_time)
    results.append(result)
for i in range(len(results)):
    print(results[i])

5.蓝桥村的真相

问题描述

在风景如画的蓝桥村,n 名村民围坐在一张古老的圆桌旁,参与一场思想的较量。这些村民,每一位都有着鲜明的身份:要么是誉满乡野的诚实者,要么是无可救药的说谎者。

当会议的钟声敲响,一场关于真理与谬误的辩论随之展开。每位村民轮流发言,编号为 i 的村民提出了这样的断言:坐在他之后的两位村民 — 也就是编号 i+1 和 i+2(注意,编号是环形的,所以如果 i 是最后一个,则 i+1 是第一个,以此类推)之中,一个说的是真话,而另一个说的是假话。

在所有摇曳不定的陈述中,有多少真言隐藏在谎言的面纱之后?

请你探索每一种可能的真假排列组合,并计算在所有可能的真假组合中,说谎者的总数。

输入格式

第一行输入一个整数 T,表示数据的组数。

接下来 T 行,每行包含一个整数 n,表示村落的人数。

输出格式

对于每组数据,输出一行包含一个整数,表示答案。

解题思路

我一直有个很好奇的问题,能否有二进制数0和1表示一切呢?这个问题暂时还没有答案,但二进制法却着实是一个很好的方法。在这个问题中我们把0看作是假的,1看作是真的,经过分析不难发现当第一个人是1时,后面只能跟10或01,即110110……或101101……(这里请进行自行思考);而当第一个人是0是,后面只能跟00或11,即000000…或011011…(这里也请自行思考)。

代码部分

import datetime
batch_size = int(input())
start_time = datetime.datetime(1970, 1, 1, 0, 0, 0)
results = []
for i in range(batch_size):
    infos = input().split()
    gap_time = int(infos[2])
    my_time = datetime.datetime.strptime(infos[0]+' '+infos[1], '%Y-%m-%d %H:%M:%S')
    delta_time = my_time - start_time
    # 创建gap_time分钟的时间间隔
    time_delta = datetime.timedelta(minutes=gap_time)
    # 间隔的时间整除时间间隔
    n = delta_time // time_delta
    result = start_time + n * datetime.timedelta(minutes=gap_time)
    results.append(result)
for i in range(len(results)):
    print(results[i])

结语

这是15届蓝桥杯的前五道题,后三道题我会在下一次发布。

作者:侠之大者231

物联沃分享整理
物联沃-IOTWORD物联网 » 一力破万法系列之暴力解决第十五届蓝桥杯省赛python组一:

发表回复