第十四届蓝桥杯Python B组省赛复盘

04-13 1370阅读

第十四届蓝桥杯Python B组省赛复盘

文章目录

  • 第十四届蓝桥杯Python B组省赛复盘
    • 试题 A: 2023
      • 【问题描述】(5 分)
      • 【思路】
      • 试题 B: 硬币兑换(5 分)
        • 【问题描述】
        • 【思路】
        • 试题 C: 松散子序列
          • 【问题描述】
          • 【输入格式】
          • 【输出格式】
          • 【样例输入】
          • 【样例输出】
          • 【评测用例规模与约定】
          • 思路
          • 试题 D: 管道
            • 【问题描述】
            • 【输入格式】
            • 【输出格式】
            • 【样例输入】
            • 【样例输出】
            • 【评测用例规模与约定】
            • 思路
            • 试题 E: 保险箱
              • 【问题描述】
              • 【输入格式】
              • 【输出格式】
              • 【样例输入】
              • 【样例输出】
              • 【评测用例规模与约定】
              • 思路
              • 试题 F: 树上选点
                • 【问题描述】
                • 【输入格式】
                • 【输出格式】
                • 【样例输入】
                • 【样例输出】
                • 【评测用例规模与约定】
                • 思路
                • 试题 G: T 字消除
                  • 【问题描述】
                  • 【输入格式】
                  • 【输出格式】
                  • 【样例输入】
                  • 【样例输出】
                  • 【样例说明】
                  • 思路
                  • 试题 H: 独一无二
                    • 【问题描述】
                    • 【输入格式】
                    • 【输出格式】
                    • 【样例输入】
                    • 【样例输出】
                    • 【样例说明】
                    • 【评测用例规模与约定】
                    • 思路
                    • 试题 I: 异或和
                      • 【问题描述】
                      • 【输入格式】
                      • 【输出格式】
                      • 【样例输入】
                      • 【样例输出】
                      • 【评测用例规模与约定】
                      • 思路
                      • 试题 J: 混乱的数组
                        • 【问题描述】
                        • 【输入格式】
                        • 【输出格式】
                        • 【样例输入】
                        • 【样例输出】
                        • 【评测用例规模与约定】
                        • 思路
                        • 总结

                          试题 A: 2023

                          【问题描述】(5 分)

                          请求出在 12345678 至 98765432 中,有多少个数中完全不包含 2023 。

                          完全不包含 2023 是指无论将这个数的哪些数位移除都不能得到 2023 。

                          例如 20322175,33220022 都完全不包含 2023,而 20230415,20193213 则 含有 2023 (后者取第 1, 2, 6, 8 个数位) 。

                          【思路】

                          1. 正则表达式

                            '''
                            正则表达式
                            '''
                            import re
                            def check(s) :
                                if re.match(r'.*2.*0.*2.*3.*', s) :
                                    return False
                                else : return True
                            st = 12345678
                            ed = 98765432
                            res = 0
                            while st sum1​,sum2​,⋅⋅⋅,sumK​} 的值达到最大,请你帮他计算这个值最大是多少。=s)打开并位于 
                                 
                                  
                                   
                                   
                                     l 
                                    
                                   
                                  
                                    l 
                                   
                                  
                                l的管道,在此时此刻可以覆盖的区间是 
                                 
                                  
                                   
                                   
                                     [ 
                                    
                                   
                                     m 
                                    
                                   
                                     a 
                                    
                                   
                                     x 
                                    
                                   
                                     ( 
                                    
                                   
                                     l 
                                    
                                   
                                     − 
                                    
                                   
                                     ( 
                                    
                                   
                                     t 
                                    
                                   
                                     − 
                                    
                                   
                                     s 
                                    
                                   
                                     ) 
                                    
                                   
                                     , 
                                    
                                   
                                     1 
                                    
                                   
                                     ) 
                                    
                                   
                                     , 
                                    
                                   
                                     m 
                                    
                                   
                                     i 
                                    
                                   
                                     n 
                                    
                                   
                                     ( 
                                    
                                   
                                     l 
                                    
                                   
                                     + 
                                    
                                   
                                     ( 
                                    
                                   
                                     t 
                                    
                                   
                                     − 
                                    
                                   
                                     s 
                                    
                                   
                                     ) 
                                    
                                   
                                     , 
                                    
                                   
                                     l 
                                    
                                   
                                     e 
                                    
                                   
                                     n 
                                    
                                   
                                     ) 
                                    
                                   
                                     ] 
                                    
                                   
                                  
                                    [max(l - (t - s), 1), min(l + (t - s), len)] 
                                   
                                  
                                [max(l−(t−s),1),min(l+(t−s),len)].

                            下面考虑区间覆盖问题,对于n个区间,可以一个个枚举区间,并对覆盖区间进行标记,然而这样的复杂度是 O ( n l e n ) O(nlen) O(nlen)。怎么优化呢?我们想到对区间进行操作的一个基础算法差分,类似于LeetCode中的区间覆盖原题。

                            '''
                            覆盖问题,二分
                            '''
                            from sys import stdin
                            def check(x) :
                                st = [0] * (m + 2)
                                for item in a :
                                    if item[1]  1
                                if check(mid) :
                                    r = mid
                                else :
                                    l = mid + 1
                            print(l)
                            

                            试题 E: 保险箱

                            时间限制: 10.0s 内存限制: 512.0MB 本题总分:15 分

                            【问题描述】

                            小蓝有一个保险箱,保险箱上共有 n 位数字。

                            小蓝可以任意调整保险箱上的每个数字,每一次操作可以将其中一位增加

                            1 或减少 1 。

                            当某位原本为 9 或 0 时可能会向前(左边)进位/退位,当最高位(左边第

                            一位)上的数字变化时向前的进位或退位忽略。

                            例如:

                            00000 的第 5 位减 1 变为 99999 ;

                            99999 的第 5 位减 1 变为 99998 ;

                            00000 的第 4 位减 1 变为 99990 ;

                            97993 的第 4 位加 1 变为 98003 ;

                            99909 的第 3 位加 1 变为 00009 。

                            保险箱上一开始有一个数字 x,小蓝希望把它变成 y,这样才能打开它,问

                            小蓝最少需要操作的次数。

                            【输入格式】

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

                            第二行包含一个 n 位整数 x 。

                            第三行包含一个 n 位整数 y 。

                            【输出格式】

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

                            【样例输入】

                            5
                            12349
                            54321
                            

                            【样例输出】

                            11

                            【评测用例规模与约定】

                            第十四届蓝桥杯Python B组省赛复盘

                            思路

                            比赛的时候看到这题秒想用BFS,但本题的数据范围实在太大,即使跑10s超过10长度的数据也跑不出来。这时我们需要挖掘一下题目中的性质:

                            1. 每一次只能让一位增加、减少1
                            2. 每一位只会向左边进位、退位,最高位的进退位忽略

                            仔细思考,根据已有性质可以推出:每一位有三种可能:进位、退位、不进不退。而且向高位进位或者退位次数,不大于1,因为进退位的目的只是更接近当前位的目标数字,对于高位的第二次改变的花费比在高位直接进行一次操作花费大。

                            由于前面的操作无后效性,可以考虑一下DP。

                            状态表示 f [ i , 0 / 1 / 2 ] f[i, 0/1/2] f[i,0/1/2], 假设原字符串和目标字符串为 s , e s, e s,e:

                            • 集合:分别表示1~i-1位已经处理到相应位置,第i位进位、退位、不进不退的最终拨转到目标数花费集合
                            • 属性:min

                              状态计算:

                              • 第i位进位: f [ i , 0 ] = ( e i + 10 − s i ) + m i n ( f [ i + 1 , 0 ] − 1 , f [ i + 1 , 1 ] + 1 , f [ i + 1 , 2 ] ) f[i, 0] = (e_i + 10 - s_i) + min(f[i + 1, 0] - 1, f[i + 1, 1] + 1, f[i + 1, 2]) f[i,0]=(ei​+10−si​)+min(f[i+1,0]−1,f[i+1,1]+1,f[i+1,2])
                              • 第i位退位: f [ i , 1 ] = ( s i + 10 − e i ) + m i n ( f [ i + 1 , 0 ] + 1 , f [ i + 1 , 1 ] − 1 , f [ i + 1 , 2 ] ) f[i, 1] = (s_i + 10 - e_i)+ min(f[i + 1, 0] + 1, f[i + 1, 1] - 1, f[i + 1, 2]) f[i,1]=(si​+10−ei​)+min(f[i+1,0]+1,f[i+1,1]−1,f[i+1,2])
                              • 第i位不进不退: f [ i , 2 ] = ∣ s i − e i ∣ + m i n ( f [ i + 1 , 0 ] + 1 , f [ i + 1 , 1 ] + 1 , f [ i + 1 , 2 ] ) f[i, 2] = |s_i - e_i| + min(f[i + 1, 0] + 1, f[i + 1, 1] + 1, f[i + 1, 2]) f[i,2]=∣si​−ei​∣+min(f[i+1,0]+1,f[i+1,1]+1,f[i+1,2])
                                n = int(input())
                                f = [[0, 0, 0] for _ in range(n + 5)]
                                st = input()
                                ed = input()
                                for i in range(n, 0, -1) :
                                    if i == n :
                                        f[i][0] = int(ed[i - 1]) + 10 - int(st[i - 1])
                                        f[i][1] = int(st[i - 1]) + 10 - int(ed[i - 1])
                                        f[i][2] = abs(int(st[i - 1]) - int(ed[i - 1]))
                                    else :
                                        f[i][0] = int(ed[i - 1]) + 10 - int(st[i - 1]) +  min(f[i + 1][0] - 1, f[i + 1][1] + 1, f[i + 1][2])
                                        f[i][1] = int(st[i - 1]) + 10 - int(ed[i - 1]) + min(f[i + 1][0] + 1, f[i + 1][1] - 1, f[i + 1][2])
                                        f[i][2] = abs(int(st[i - 1]) - int(ed[i - 1])) + min(f[i + 1][0] + 1, f[i + 1][1] + 1, f[i + 1][2])
                                print(min(f[1][0], f[1][1], f[1][2]))
                                

                                思路感觉没毛病,但在dotcpp上只能过一个点,家人们谁懂啊

                                试题 F: 树上选点

                                时间限制: 10.0s 内存限制: 512.0MB 本题总分:15 分

                                【问题描述】

                                给定一棵树,树根为 1,每个点的点权为 V i V_i Vi​ 。

                                你需要找出若干个点 P i P_i Pi​,使得:

                                1. 每两个点 P x P y P_x P_y Px​Py​ 互不相邻;
                                2. 每两个点 P x P y P_x P_y Px​Py​ 与树根的距离互不相同;
                                3. 找出的点的点权之和尽可能大。

                                  请输出找到的这些点的点权和的最大值。

                                【输入格式】

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

                                第二行包含 n − 1 个整数 F i F_i Fi​ ,相邻整数之间使用一个空格分隔,分别表示

                                第 2 至 n 个结点的父结点编号。

                                第三行包含 n 个整数 V i V_i Vi​,相邻整数之间使用一个空格分隔,分别表示每个

                                结点的点权。

                                【输出格式】

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

                                【样例输入】

                                5
                                1 2 3 2
                                2 1 9 3 5
                                

                                【样例输出】

                                11

                                【评测用例规模与约定】

                                第十四届蓝桥杯Python B组省赛复盘

                                思路

                                题目大意是,选的节点不具有父子关系,且不可以深度相同,最终使选择的点价值最大。

                                明显的状态机树形DP。

                                对于一个确定的节点 i i i,要么取要么不取。

                                分情况讨论:

                                • 取 : 则子节点一定不能取
                                • 不取:则可以取一个子节点,也可以不取

                                  靠写不出来了,感觉又BFS又DFS好烦,过了过了

                                  试题 G: T 字消除

                                  时间限制: 10.0s 内存限制: 512.0MB 本题总分:20 分

                                  【问题描述】

                                  小蓝正在玩一款游戏,游戏中有一个 n × n 大小的 01 矩阵 A i , j A_{i, j} Ai,j​ 。

                                  小蓝每次需要选择一个 T 字型的区域,且这个区域内至少要有一个 1 。选

                                  中后,这个区域内所有的元素都会变成 0 。

                                  给定游戏目前的矩阵,小蓝想知道他最多可以进行多少次上述操作。

                                  T 字型区域是指形如 ( x − 1 , y ) ( x , y ) ( x + 1 , y ) ( x , y + 1 ) (x − 1, y) (x, y) (x + 1, y) (x, y + 1) (x−1,y)(x,y)(x+1,y)(x,y+1) 的四个点所形成的区

                                  域。其旋转 90, 180, 270 度的形式同样也视作 T 字形区域。

                                  【输入格式】

                                  输入包含多组数据。

                                  输入的第一行包含一个整数 D 表示数据组数。

                                  对于每组数据,第一行包含一个整数 n 。

                                  接下来 n 行每行包含 n 个 0 或 1,表示矩阵 A i , j A_{i, j} Ai,j​ 的每个位置的值。

                                  【输出格式】

                                  输出 D 行,每行包含一个整数表示小蓝最多可以对当前询问中的矩阵操作

                                  的次数。

                                  【样例输入】

                                  1
                                  3
                                  001
                                  011
                                  111
                                  

                                  【样例输出】

                                  5

                                  【样例说明】

                                  我们用 X 表示某次操作选中的 T 字形,以下给出一种可行方案:

                                  第十四届蓝桥杯Python B组省赛复盘

                                  【评测用例规模与约定】

                                  第十四届蓝桥杯Python B组省赛复盘

                                  思路

                                  麻了,题目看懂了想dfs做但无从下手,感觉是个贪心的题,去你的。

                                  试题 H: 独一无二

                                  时间限制: 30.0s 内存限制: 512.0MB 本题总分:20 分

                                  【问题描述】

                                  有一个包含 n 个点,m 条边的无向图,第 i 条边的边权为 c i c_i ci​,没有重边和

                                  自环。设 s i s_i si​ 表示从结点 1 出发到达结点 i 的最短路的不同路径数 ( i ∈ [1, n] ),

                                  显然可以通过删除若干条边使得 s i = 1 s_i = 1 si​=1,也就是有且仅有一条从 1 到 i 的最短

                                  路,且保持最短路的路径长度不变,对于每个 i ,求出删除边数的最小值。

                                  【输入格式】

                                  输入的第一行包含两个正整数 n, m。

                                  接下来 m 行,每行包含三个正整数 u i , v i , c i u_i, v_i, c_i ui​,vi​,ci​ 表示第 i 条边连接的两个点的

                                  编号和边权。

                                  【输出格式】

                                  输出 n 行,第 i 行包含一个正整数表示对于结点 i ,删除边数的最小值,

                                  如果 1 和 i 不连通,输出 −1 。

                                  【样例输入】

                                  4 4
                                  1 2 1
                                  1 3 2
                                  2 4 2
                                  3 4 1
                                  

                                  【样例输出】

                                  0

                                  0

                                  0

                                  1

                                  【样例说明】

                                  在给定的图中,只有 s4 一开始为 2,因为有两条最短路:1 → 2 → 4, 1 →

                                  3 → 4,任意删掉一条边后,就可以只剩一条最短路。

                                  【评测用例规模与约定】

                                  第十四届蓝桥杯Python B组省赛复盘

                                  思路

                                  听说是什么最短路+dp转移,听都没听过,以后有缘再见吧!

                                  试题 I: 异或和

                                  时间限制: 15.0s 内存限制: 512.0MB 本题总分:25 分

                                  【问题描述】

                                  给一棵含有 n 个结点的有根树,根结点为 1 ,编号为 i 的点有点权 a i a_i ai​ ( i ∈ [ 1 , n ] ) (i ∈ [1, n]) (i∈[1,n])。现在有两种操作,格式如下:

                                  • 1 x y 该操作表示将点 x 的点权改为 y 。

                                  • 2 x 该操作表示查询以结点 x 为根的子树内的所有点的点权异或和。

                                  现有长度为 m 的操作序列,请对于每个第二类操作给出正确的结果。

                                  【输入格式】

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

                                  第二行包含 n 个整数 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1​,a2​,...,an​ ,相邻整数之间使用一个空格分隔。

                                  接下来 n − 1 行,每行包含两个正整数 u i , v i u_i, v_i ui​,vi​ ,表示结点 u i u_i ui​ 和 v i v_i vi​ 之间有一条

                                  边。

                                  接下来 m 行,每行包含一个操作。

                                  【输出格式】

                                  输出若干行,每行对应一个查询操作的答案。

                                  【样例输入】

                                  4 4
                                  1 2 3 4
                                  1 2
                                  1 3
                                  2 4
                                  2 1
                                  1 1 0
                                  2 1
                                  2 2
                                  

                                  【样例输出】

                                  4

                                  5

                                  6

                                  【评测用例规模与约定】

                                  第十四届蓝桥杯Python B组省赛复盘

                                  思路

                                  一个dfs序模板

                                  首先要知道异或和的一些性质 :

                                  0异或任何数都是这个数本身

                                  任何数异或本身等于0

                                  所以异或中加减操作都集中在异或运算上

                                  具体来说,先处理出树的dfs序列,然后初始化树状数组。dfs序列易于处理一个以u为根的子树,在序列中表示一个区间。用树状数组处理区间和单点操作。

                                  import sys
                                  sys.setrecursionlimit(60000)
                                  n, m = map(int, input().split())
                                  id = [0] # 表示dfs序
                                  inn = [0] * (n + 1) #以i节点为根的子树在dfs序开始位置
                                  out = [0] * (n + 1) #以i节点为根的子树在dfs序末尾位置
                                  h = [-1] * (2 * n + 7)
                                  e = [0] * (2 * n + 7)
                                  ne = [-1] * (2 * n + 7)
                                  idx = 0
                                  tr = [0] * (n + 7) # 树状数组,存储(x - lowbit(x), x]区间内的异或和
                                  def lowbit(x) :
                                      return x & -x
                                  def sum(x, c) : # 修改操作
                                      i = x
                                      while i  
                                          
                                          
                                          
                                            A 
                                           
                                          
                                            j 
                                           
                                          
                                         
                                        
                                          A_i > A_j 
                                         
                                        
                                      Ai​>Aj​ 。

                                  如果存在多个这样的数组,请输出字典序最小的那个。

                                  【输入格式】

                                  输入一行包含一个整数表示 x 。

                                  【输出格式】

                                  输出两行。

                                  第一行包含一个整数 n ,表示所求出的数组长度。

                                  第二行包含 n 个整数 A i A_i Ai​,相邻整数之间使用一个空格分隔,依次表示数组

                                  中的每个数。

                                  【样例输入】

                                  3
                                  

                                  【样例输出】

                                  3

                                  3 2 1

                                  【评测用例规模与约定】

                                  第十四届蓝桥杯Python B组省赛复盘

                                  思路

                                  对于这题,我决定直接打表得分,蚊子肉也是肉啊

                                  x = int(input())
                                  if x == 1:
                                      print(2)
                                      print(2, 1)
                                  if x == 2:
                                      print(3)
                                      print(2, 1, 1)
                                  if x == 3:
                                      print(3)
                                      print(3, 2, 1)
                                  if x == 4:
                                      print(4)
                                      print(2, 2, 1, 1)
                                  if x == 5:
                                      print(4)
                                      print(3, 2, 1, 1)
                                  if x == 6:
                                      print(4)
                                      print(4, 3, 2, 1)
                                  if x == 7:
                                      print(5)
                                      print(3, 2, 2, 2, 1)
                                  if x == 8:
                                      print(5)
                                      print(3, 3, 2, 1, 1)
                                  if x == 9:
                                      print(5)
                                      print(4, 3, 2, 1, 1)
                                  if x == 10:
                                      print(5)
                                      print(5, 4, 3, 2, 1)
                                  

                                  总结

                                  麻了,做这B样也能省一,还挺开心。感觉还差挺多的,很多读题失误,很多题没好好体会导致无谓失分,很可惜。继续加油努力吧,冲刺国赛。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]