第一次参加蓝桥杯总结与反思:
赛前状态反思:
赛前那段时间,确实不够努力,没有完全执行自己和老师制定的计划,没有充分利用时间去进行算法训练,过于松懈了。虽然后来在老师的指点下,开始认真总结写过的算法题,但是做题的数量还是远远不够。
赛中状态反思:
比赛时候,紧张,慌乱,害怕,各种情绪交杂在一起,加上考场出现的一些突发情况,前一个小时我几乎不能平静下来认真做题。做题过程中也是手忙脚乱,瞻前顾后。
赛后反思总结:
比赛完之后,我第一个想法就是,备战第16届蓝桥杯。因为这次的蓝桥杯让我对比赛有了初步的认识,我也意识到,学习算法和积累沉淀的重要性。我在往后学习和生活中需要做的,一是在比赛或者其他重要考试或者大场合中能够做到临危不惧,及时调整好自己的状态,找到属于自己的节奏;二是不打无准备的仗,这次蓝桥杯比赛显然我准备的还远远不够充分,不够扎实;三是自律、严格执行计划,计划制定完成之后,应该严格执行,这是我需要改正的。在写这届蓝桥杯题目分析的时候,我上网看到了好多方法,里面解决问题调用的函数里面有些甚至我非常陌生,一是我能力不够,二是我没好好利用帮助文档。
总之,这次蓝桥杯我写得很失败,但无疑是给我沉重一击,给我很多的启发,让我及时端正学习态度,时常反思,时常进步。
题目分析:
关于题目的解题过程和思路,我在整理的时候,会先写出我比赛时的思路,也会写出在网上查找到的一些思路和方法。这里面或许会有错误,在看到优秀的题解我也会及时补充进来。
题目A:穿越时空之门
【问题描述】
随着2024年的钟声回荡,传说中的时空之门再次敞开。这扇门是一条神秘的通道,它连接着二进制和四进制不同的数码领域,等待着勇者们的探索。
在二进制的领域里,勇者的力量被转换成力量数值的二进制表示各数位之和。
在四进制的领域里,力量的转换规则相似,变成了力量数值的四进制表示中各数位之和。
穿越这扇时空之门的条件是严苛的:当且仅当勇者在二进制领域的力量时,他才能够成功地穿越。
国王选定了小蓝作为领路人,带领着力量值从1到2024的勇者们踏上了这段探索未知的旅程。作为小蓝的助手,你的任务是帮助小蓝计算出,在这2024位勇者中,有多少人符合穿越时空之门的条件。
🤔数字转二进制、四进制,数位之和相等
答案:63
def sum_jinzhi(a,k):
"""将数字a转换为k进制,求数值位和"""
sum=0
while a!=0:
sum+=a%k
a=a//k
return sum
num=0
for i in range(1,2024):
if sum_jinzhi(i,2)==sum_jinzhi(i,4):
num+=1
print(num)
题目B:数字串个数
【问题描述】
小蓝想要构造出一个长度为10000的数字字符串 ,有以下要求:
1、小蓝不喜欢数字0,所以数字字符串中不可以出现0
2、小蓝不喜欢数字3和7,所以数字字符串中必须有3和7这两个数字
请问满足题意的数字字符串有多少个?这个数字会很大,只需要输出对10**9+7取余后的结果
🤔当时想着暴力解决,但是会出现下面的报错
"Exceeds the limit (4300 digits) for integer string conversion"表示整数字符串转换时超过了限制,限制为4300位数字。要解决这个问题,可以使用sys.set_int_max_str_digits()函数来增加限制。sys.set_int_max_str_digits()函数是Python中的一个函数,用于设置整数字符串转换的最大位数限制。通过调用该函数并传入一个较大的值,可以增加整数字符串转换的限制。
可以这样解决,sys.set_int_max_str_digits(0),表示没有限制
但是这样运行时间太长 ,但代入小数值运行结果正确的
🤔更好的方法:容斥原理
容斥原理:先不考虑重叠情况,把包含于某内容种的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数方法叫做容斥原理。
本题运用容斥原理的解题思路:
首先考虑每一位数字的选择。由于数字字符串中不能出现0,所以每一位数字有9种选择(1-9)。因此,长度位10000的数字字符串有pow(9,n)种可能性。
题目要求必须包含3和7,因此需要减去不包含3和7的情况。不包含3有pow(8,n)种,不包含7的有pow(8,n)种。
但是上述操作会将同时不含3和7的情况计算两次,因此需要再加回来。即不含3也不含7的情况有pow(7,n)种。
综上,满足的数字字符串数量为pow(9,n)-2*pow(8,n)+pow(7,n)。
最后对结果取mod=int(1e9+7)的余数
pow(x,y,z)函数:
x:底数,不可省 y:指数,不可省
z:取余数字,可省,当z存在时,函数返回值等于pow(x,y)%z
答案:157509472
mod=int(1e9+7)
n=10000
cnt=pow(9,n)
cnt-=2*pow(8,n)
cnt+=pow(7,n)
cnt%=mod
print(cnt)
题目C:连连看
【问题描述】
小蓝在和朋友们玩一种新的连连看游戏。在一个n*m的矩形网格中,每个格子中都有一个整数,第i 行第j 列上的整数为Ai,j,玩家需要在这个网格中寻找一对格子(a,b)-(c,d)使得这两个格子中的整数Aa,b和Ac,d相等,且它们的位置满足|a-c|=|b-d|>0。请问在这个n*m的矩形网格中有多少对这样的格子满足条件。
【输入格式】
输入的第一行包含两个正整数n,m,用一个空格分隔。
接下来的n行,第i 行包含m个正整数Ai,1、Ai2、.....Ai,m,相邻整数之间使用一个空格分隔。
【输出格式】
输出一行包含一个整数表示答案。
【样例】
输入:
3 2
1 2
2 3
3 2
输出:
6
说明:
一共有以下6对格子:(1,2)-(2,1),(2,2)-(3,1),(2,1)-(3,1),(2,1)-(1,2),(3,1)-(2,2),(3,2)-(2,1)。
【评测用例规模与约定】
20% 1<=n,m<=50
100% 1<=n,m<=1000,1<=Ai,j<=1000
由题意可知,(a,b)-(c,d)中的两个元素位于同一斜线上
n, m = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(n)]
# A[a][b] = A[c][d], 处于同一斜线上
cnt = 0
for i in range(n):
for j in range(m):
# 只跟当前行以下的行比较
# 向左下角
for p in range(1, min(n - i, j + 1)):
cnt += A[i][j] == A[i + p][j - p]
# 向右下角
for p in range(1, min(n - i, m - j)):
cnt += A[i][j] == A[i + p][j + p]
print(cnt * 2)
题目D:神奇闹钟
【问题描述】
小蓝发现了一个神奇的闹钟,从纪元时间(1970年1月1日00:00:00)开始,每经过x分钟,这个闹钟便会触发一次响铃(纪元时间也会响铃)。这引起了小蓝的兴趣,他想要好好研究一下这个闹钟。
对于给出的任意一个格式为yyyy-MM-dd HH:mm:ss的时间,小蓝想要知道在这个时间点之前(包含这个时间点)的最近的一次闹铃时间是哪个时间?
注意,你不必考虑时区问题。
【输入格式】
输入的第一行包含一个整数T,表示每次输入包含T组数据。
接下来依次描述T组数据。
每组数据一行,包含一个时间(格式为yyyy-MM-dd HH:mm:ss)和一个整数x,其中x表示闹铃时间间隔(单位为分钟)。
【输出格式】
输出T行,每行包含一个时间(格式为yyyy-MM-dd HH:mm:ss),依次表示每组数据的答案。
【样例】
输入:
2
2016-09-07 18:24:33 10
2037-01-05 01:40:43 30
输出:
2016-09-07 18:20:00
2037-01-05 01:30:00
【评测用例规模与约定】
100% 1<=T<=10,1<=x<=1000
🤔当时想的是计算出来两个时间相差多少分钟,其中包含闰年的判断等等,其中结果的秒必是00,很难计算,最后也没写出来。
🤔下面这种方法是在网上看到的,很厉害。但这涉及到我的知识盲区了😵,部分函数方法我几乎没用过。
import time
fmt="%Y-%m-%d %H:%M:%S"
for i in range(int(input())):
#从最右边开始,进行一次拆分,以空格分隔
datetime,x=input().rsplit(maxsplit=1)
#x是分钟表示,乘以60,以秒表示
x=int(x)*60
#t为输入的时间与纪元时间所差的秒数,四舍五入。
t=round(time.mktime(time.strptime(datetime,fmt)))
print(time.strftime(fmt,time.localtime(t-t%x)))
str.rsplit(sep=None,maxsplit=-1)
描述:
返回一个由字符串内单词组成的列表,使用sep作为分隔字符串。
如果给出了maxsplit,则最多进行maxsplit次拆分,从最右边开始。
除了从右边开始拆分,rsplit()的其他行为都类似与split()。
参数说明:
sep:分隔符,默认为所有的空格符,包括空格、换行(\n),制表符(\t)等。
maxsplit:分割次数,默认为-1,即分割所有
返回值:返回分割后的字符串列表。
round()是python中自带的一个函数,用于数字的四舍五入。但round()的输出结果和python的版本有关:在python3中,round(1.0/2.0)=0;在python2中,round(1.0/2.0)=1
round(number,digits)
①digits>0,四舍五入到指定的小数位
②digits=0,四舍五入到最接近的整数
③digits<0,在小数点左侧进行四舍五入
④如果只有number一个参数,相当于digits=0
四舍五入规则:
①要求保留位数的后一位小于等于4,则舍去。
如5.214,保留小数点后两位,5.21
②要求保留位数的后一位等于5,且该位数后无数字,则不进位,直接舍去。
如5.215,保留小数点后两位,5.21
③要求保留位数的后一位等于5,且该位数后有数字,则进位
如5.2151,保留小数点后两位,2.22
④要求保留位数的后一位大于等于6,则进位。
如5.216,保留小数点后两位,5.22
time.mktime(t)
参数:t:结构化的时间或者完整的9位元组元素。
返回值:返回用描述来表示时间的浮点数,返回自1970年1月1日00:00:00到现在所经过的秒数。
如果输入的值不是一个合法的时间,将触发OverflowError或ValueError。
例:
import time
t = (2009, 2, 17, 17, 3, 38, 1, 48, 0)
secs = time.mktime( t ) #1234915418.000000time.strftime(format[,t])
描述:用于格式化时间,返回以可读字符串表示当地时间,格式由参数format决定。
参数:format:格式字符串。 t:可选参数,是一个struct_time对象
返回值:返回以可读字符串表示当地时间。
time.strptime(string[,format])
描述:根据指定格式把一个时间字符串解析为时间元组。
参数:string:时间字符串。 format:格式化字符串。
返回值:返回struct_time对象。
经过这题,我意识到,时间的相关函数需要专门去学习一下。
题目E:蓝桥村的真相
【问题描述】
在风景如画的蓝桥村,n 名村民围坐在一张古老的圆桌旁,参与一场思想 的较量。这些村民,每一位都有着鲜明的身份:要么是誉满乡野的诚实者,要 么是无可救药的说谎者。
当会议的钟声敲响,一场关于真理与谬误的辩论随之展开。每位村民轮流 发言,编号为 i 的村民提出了这样的断言:坐在他之后的两位村民------也就是 编号 i + 1 和 i + 2(注意,编号是环形的,所以如果 i 是最后一个,则 i + 1 是 第一个,以此类推)之中,一个说的是真话,而另一个说的是假话。
在所有摇曳不定的陈述中,有多少真言隐藏在谎言的面纱之后?
请你探索每一种可能的真假排列组合,并计算在所有可能的真假组合中, 说谎者的总数。
【输入格式】
输入的第一行包含一个整数 T,表示每次输入包含 T 组数据。
接下来依次描述 T 组数据。
每个数据一行包含一个整数 n,表示村落的人数。
【输出格式】
输出 T 行,每行包含一个整数,依次表示每组数据的答案。
【样例】
输入:
2
3
3
输出:
6
6
【评测用例规模与约定】
10% T=1,3<=n<=10
40% 1<=T<=10**2,3<=n<=3*10**3
100% 1<=T<=10**5,3<=n<=10**18
🤔这题我当时第一反应是动态规划,但是没写出来状态转移方程。不了了之。
🤔下面是网上一种解法:
num=int(input())
re=[]
for i in range(num):
n=int(input())
re.append(n*((n+1)//2))
for i in range(num):
print(re[i])
!!题目F:魔法巡游
【问题描述】
在蓝桥王国中,两位魔法使者,小蓝与小桥,肩负着维护时空秩序的使命。 他们每人分别持有 N 个符文石,这些石头被赋予了强大的力量,每一块上都刻 有一个介于 1 到 之间的数字符号。小蓝的符文石集合标记为S1,S2,.......Sn , 小桥的则为t1,t2,.....tn 。
两位魔法使者的任务是通过使用符文石,在各个时空结点间巡游。每次巡游遵循这样一条法则:当小蓝使用了符文石 Si到达新的结点后,小桥必须选用 一个序号更大的符文石(即某个tj满足 j > i)前往下一个结点。同理,小桥抵 达之后,小蓝需要选择一个序号 k > j 的符文石Sk继续他们的巡游。
为了成功地穿梭时空,两个连续使用的符文石上的数字符号必须有共鸣, 这种共鸣只有当数字符号中至少包含一个特定的元素——星火(数字 0)、水波 (数字 2)或者风语(数字 4)时,才会发生。例如,符号序列 126, 552, 24, 4 中 的每对连续符文都包含了至少一个共鸣元素,则它们是一系列成功的巡游;而 如果是 15, 51, 5,则不成立,因为它们之间的共鸣元素不包含星火、水波或风语 中的任意一个。
小蓝总是先启程,使用他的符文石开启巡游。
你的任务是计算这对魔法使者能够执行的最长时空巡游序列的长度。这样的序列形式为 si,iti2,si3,ti4,......其中序列索引满足i1<i2<i3<i4<....... ,并且序列中每一对相邻的符文石都至少包含一个共鸣元素。
【输入格式】
输入的第一行包含一个整数 N,表示每位魔法使者持有的符文石数量。
第二行包含 N 个整数 s1,s2,....sn,相邻整数之间使用一个空格分隔,表示小蓝的符文石上刻有的数字符号。
第三行包含 N 个整数 t1,t2,....tn ,相邻整数之间使用一个空格分隔,表示小桥的符文石上刻有的数字符号。
【输出格式】
输出一行包含一个整数,表示小蓝和小桥在遵守所有规则的情况下,最多能进行多少次时空巡游。
【样例】
输入:
5
126 393 581 42 44
204 990 240 46 52
输出:
4
说明:小蓝和小桥可以选择以下符文石序列进行巡游:S1(126)->t3(240)->s4(42)->t5(52)这里,数字2作为共鸣元素连接了s1和t3、s4和t5,数字2、4作为共鸣元素连接了t3和s4。
【评测用例规模与约定】
30% 1<=N<=10**3,1<=si,ti<=10**5
100% 1<=N<=10**5,1<=si,ti<=10**9
!!!题目G:缴纳过路费
【问题描述】
在繁华的商业王国中,N 座城市被 M 条商路巧妙地连接在一起,形成了一 个错综复杂的无向图网络。每条商路是双向通行的,并且任意两座城市之间最 多只有一条直接的商路。每条商路都有它的规则,其中最引人注目的就是穿过商路,需要缴纳过路费。因此,商人们在选择商路时必须格外认真。
有一位名叫小蓝的商人,他对于商路的花费有着自己独到的见解。在小蓝 眼中,一条路线包含一条或多条商路,但路线的成本并不是沿途累积的过路费 总和,而是这条路线上最贵的那一次收费。这个标准简单而直接,让他能迅速 评估出一条路线是否划算。
于是,他设立了一个目标,即找出所有城市对,这些城市之间的最低路线 成本介于他心中预设的两个数 L 和 R 之间。他相信,这样的路线既不会太廉 价,以至于路况糟糕;也不会过于昂贵,伤害他精打细算的荷包。
作为小蓝的助手,请你帮助小蓝统计出所有满足条件的城市对数量。
【输入格式】
输入的第一行包含四个整数 N, M, L, R,表示有 N 座城市和 M 条双向通行 的商路,以及小蓝心中预设的最高过路费的下限 L 和上限 R。
接下来 M 行,每行包含三个整数 u, v, w,表示城市 u 和城市 v 之间有一条 双向通行的商路,过路费为 w。保证每对城市之间最多只有一条直接的商路。
【输出格式】
输出一行包含一个整数,表示满足条件的城市对数量。
【样例】
输入:
5 5 1 2
1 2 2
1 3 5
1 4 1
2 4 5
2 5 4
输出:
3
说明:
满足条件的城市对有(1,2),(1,4),(2,4)
!!!题目H:纯职业小组
【问题描述】
在蓝桥王国,国王统治着一支由 n 个小队组成的强大军队。每个小队都由相同职业的士兵组成。具体地,第 i 个小队包含了 bi 名职业为 ai 的士兵。
近日,国王计划在王宫广场举行一场盛大的士兵检阅仪式,以庆祝王国的繁荣昌盛。然而,在士兵们入场的过程中,一场突如其来的风暴打乱了他们的 行列,使得不同小队的士兵混杂在一起,次序乱成一团,尽管国王无法知道每个士兵的具体职业,但为了确保仪式能顺利进行,国王打算从这些混乱的士兵中选出一部分,组成 k 个"纯职业小组"进行检阅。 一个"纯职业小组"定义为由 3 名同职业的士兵组成的队伍。
请问,国王至少需要选择多少名士兵,才能确保这些士兵可以组成 k 个 "纯职业小组"。
【输入格式】
输入的第一行包含一个整数 T,表示每次输入包含 T 组数据。
接下来依次描述 T 组数据。
每组数据的第一行包含两个整数 nt和 k ,用一个空格分隔,表示小队的数量和要组成的纯职业小组的数量。
接下来的 nt行,每行包含两个整数ai 和bi ,用一个空格分隔,表示第 i 个小队中士兵的职业和数量。
【输出格式】
输出 T 行,每行包含一个整数,依次表示每组数据的答案,即为了组成 k 个"纯职业小组",国王至少需要选择的士兵数量。如果无论如何也无法组成 k 个"纯职业小组",则输出 −1。