第十三届蓝桥杯省赛 python B组复盘(三道代码题全AC居然省一了)

Posted 风信子的猫Redamancy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十三届蓝桥杯省赛 python B组复盘(三道代码题全AC居然省一了)相关的知识,希望对你有一定的参考价值。

第十三届蓝桥杯省赛 python B组复盘(三道代码题全AC居然省一了)

🏆获奖感言

芜湖,努力是有结果的,这一个多月慢慢刷题,把数据结构和算法设计一步一步捡起来,也好好学习python的知识

终于一分耕耘一分收获咯,嘻嘻,开心,我居然拿了省一

其实考完以后,我个人感觉有点凉,因为感觉稍微的有点没什么信心,最后一道题没写几乎,倒数第二道题也胡乱写了一通,导致考完我就觉得随缘了,努努力就好了,没有抱太大希望,并且这之后,一点都不敢看这些试题了,给自己好好放松了

结果!!!我居然也有省一哈哈哈,我听到我朋友告诉我,我好开心哈哈,连忙分享给朋友们,也收到了恭喜,不错不错,嘻嘻,运气不错嘻嘻,而且排名也还是可以的,在前3%左右,看起来国奖还是有点希望的。

也有小伙伴跟我说,看了我讲解的视频,也拿了省一,都很不错,希望继续努力,在国赛也能拿个国奖回来。

好咯,开始复盘一下这次的蓝桥杯之路,顺便补补自己的短板,之后,也会出一期讲解视频嘻嘻

接下来所有的题目实际上都可以在C语言网进行提交,这里给出网址2022年第十三届蓝桥杯大赛软件类省赛Python大学B组真题

🌟 试题 A:排列字母

🤔 思路

这道题其实简单来说,就是一个排序问题,所以我几乎没怎么思考,直接调用sort函数,我后面还仔细看了看,害怕第一道题怎么那么简单哈哈,不过第一道题简单确实正常。

💻 代码

s = "WHERETHEREISAWILLTHEREISAWAY"
print(''.join(sorted(s))) # AAAEEEEEEHHHIIILLRRRSSTTWWWY

🌟 试题 B:寻找整数

🤔 思路

这道题我现在想起来,依旧是心有余悸

当时我觉得最简单就是穷举嘛,反正硬生生穷举,并且考虑到python速度比较慢,我还用了C++来穷举,我想着四个小时起码出来吧,但是我大意了,即使后面我疯狂穷举,一天都还没出来,我无了,麻了。

听说正解是中国剩余定理,我在查资料的时候也看到一些有趣的解法,大家都还是蛮聪明的

有个朋友用暴力也搞了出来,真的人才,只能说这种枚举很聪明,但是感觉可遇不可求,他枚举到了一个等差数列,就是在满足一定条件下的数据是一个等差数列,接着就利用等差数列这个数据进行暴力穷举,30s得出最后答案,大家有兴趣也可以看一看2022第十三届蓝桥杯PythonB组

暴力三步走:

1.枚举数据找规律:取表后面5个大数判断更容易找到大数据,得到关键数据。

2.找出规律求公式:这些数字是按判断求得的,所以一定存在公式。

3.遍历公式找答案:通过公式进行快速遍历,30s轻松找到十六位数的答案。

💻 代码

#1.枚举数据找规律
i=1
while True:
    flag=True
    if i%49!=46:
        flag=False
    if i%48!=41:
        flag=False
    if i%47!=5:
        flag=False
    if i%46!=15:
        flag=False
    if i%45!=29:
        flag=False
    if flag:
        print(i)
    i+=1
'''
4772009
42909689
81047369
119185049
157322729
···
'''
#2.找出规律求公式
a=[4772009, 42909689, 81047369, 119185049,157322729]
#发现存在等差数列
print(a[1]-a[0])#38137680
print(a[2]-a[1])#38137680
print(a[3]-a[2])#38137680
k=38137680
b=4772009
#求出公式
y=k
#遍历公式
x=0
k=38137680
b=4772009
while True:
    flag=True
    y=k*x+b
    for i,j in mod:
        if y%i !=j:
            flag=False
            break
    if flag==True:
        print(y)#2022040920220409
        break
    x+=1

🌟 试题 C:纸张尺寸

题目描述

在 ISO 国际标准中定义了 A0 纸张的大小为 1189mm × 841mm,将 A0 纸沿长边对折后为 A1 纸,大小为 841mm × 594mm,在对折的过程中长度直接取下整(实际裁剪时可能有损耗)。将 A1 纸沿长边对折后为 A2 纸,依此类推。

输入纸张的名称,请输出纸张的大小。

输入

输入一行包含一个字符串表示纸张的名称,该名称一定是 A0、A1、A2、A3、A4、A5、A6、A7、A8、A9 之一。

输出

输出两行,每行包含一个整数,依次表示长边和短边的长度。

样例输入

A0

样例输出复制

1189
841

🤔 思路

这道题我觉得,相对于来说,还是比较简单的,因为其实题目已经固定了A0的纸张的大小,之后就是对A0的纸张不断的折叠。然后A后面的数字就是折叠的次数,比如A1是折叠一次,A2是折叠2次。。。

这之中注意两个点,第一,我们是对较长的边进行折叠

第二,就是我们首先输出长边,然后输出短边

💻 代码

s = input() 

t = int(s[-1]) # 最后一个数字也就是迭代的次数
w,h = 1189,841

for i in range(t):
    if w > h:
        w = w//2
    else:
        h = h//2
if w > h:
    print(w)
    print(h)
else:
    print(h)
    print(w)

大家的代码也可以去这里提交 🚀纸张尺寸

🌟 试题 D:数位排序

题目描述

小蓝对一个数的数位之和很感兴趣,今天他要按照数位之和给数排序。当两个数各个数位之和不同时,将数位和较小的排在前面,当数位之和相等时,将数值小的排在前面。

例如,2022 排在 409 前面,因为 2022 的数位之和是 6,小于 409 的数位之和 13。

又如,6 排在 2022 前面,因为它们的数位之和相同,而 6 小于 2022。

给定正整数 n,m,请问对 1 到 n 采用这种方法排序时,排在第 m 个的元素是多少?

输入

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

第二行包含一个正整数 m。

输出

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

样例输入

13
5

样例输出

3

提示

1 到 13 的排序为:1, 10, 2, 11, 3, 12, 4, 13, 5, 6, 7, 8, 9。第 5 个数为 3。

对于 30% 的评测用例,1 ≤ m ≤ n ≤ 300。

对于 50% 的评测用例,1 ≤ m ≤ n ≤ 1000。

对于所有评测用例,1 ≤ m ≤ n ≤ 1 0 6 10^6 106

🤔 思路

我觉得这其实就是一个排序问题,对于python来说,那我值需要设置一个排序规则即可,实际对于C++也有sort函数

所以思路就出来,首先创建我们需要的数组,然后定义一个排序规则,这个排序规则就是依照数位之和排序,所以定义了一个cmp函数计算数位之和,最后输出第m个数字就可以得到答案了

💻 代码

n = int(input())
l = [i for i in range(1,n+1)]
# 设置一个排序规则,计算数位之和
def cmp(x):
    ans = 0
    while x:
        ans += x%10
        x = x//10
    return ans 

l.sort(key = cmp)
m = int(input())
print(l[m-1])

大家的代码也可以去这里提交 🚀数位排序

🌟 试题 E:蜂巢

题目描述

蜂巢由大量的六边形拼接而成,定义蜂巢中的方向为:0 表示正西方向,1 表示西偏北 60◦,2 表示东偏北 60◦,3 表示正东,4 表示东偏南 60◦,5 表示西偏南 60◦。

对于给定的一点 O,我们以 O 为原点定义坐标系,如果一个点 A 由 O 点先向 d 方向走 p 步再向 (d + 2) mod 6 方向(d 的顺时针 120◦ 方向)走 q 步到达,则这个点的坐标定义为 (d, p, q)。在蜂窝中,一个点的坐标可能有多种。

下图给出了点 B(0, 5, 3) 和点 C(2, 3, 2) 的示意。

给定点 (d1, p1, q1) 和点 (d2, p2, q2),请问他们之间最少走多少步可以到达?

输入

输入一行包含 6 个整数 d1, p1, q1, d2, p2, q2 表示两个点的坐标,相邻两个整数之间使用一个空格分隔。

输出

输出一行包含一个整数表示两点之间最少走多少步可以到达。

样例输入

0 5 3 2 3 2

样例输出

7

提示

对于 25% 的评测用例,p1, p2 ≤ 1 0 3 10^3 103
对于 50% 的评测用例,p1, p2 ≤ 1 0 5 10^5 105
对于 75% 的评测用例,p1, p2 ≤ 1 0 7 10^7 107
对于所有评测用例,0 ≤ d1, d2 ≤ 5,0 ≤ q1 < p1 ≤ 1 0 9 10^9 109,0 ≤ q2 < p2 ≤ $10^9 $。

🤔 思路

这道题也真是搞脑子呀,当时看到这道题,想了好一会,想了很多种坐标系,结果几乎一个都没有对

在考完试和朋友讨论的时候,他跟我说,这道题可以用向量的想法,真是妙啊,那我们来看看

这样我们就可以将得到的坐标转化成0方向和1方向的向量,之后两个点的距离,就可以用我们的向量相减表示

不过之后,求最近距离的时候又分为两种情况,一种是符号相同的情况,符号相同的时候,也就是a+b或者-a-b这时候我们的距离就是|a+b|,也就是a+b的绝对值

但是对于符号不同的情况,我们就要取max(|a|,|b|)了,这里大概画图理解一下

💻 代码

d1,p1,q1,d2,p2,q2=map(int,input().split())

# 全部转化为0 方向 和 1方向的向量
def change(d,p,q):
    if d==0:return (p-q,q)
    if d==1:return (-q,p)
    if d==2:return (-p,p-q)
    if d==3:return (q-p,-q)
    if d==4:return (q,-p)
    if d==5:return (p,q-p)
s1=change(d1,p1,q1)
s2=change(d2,p2,q2)

# 向量的剑法
s=[s1[0]-s2[0],s1[1]-s2[1]]
a,b=s[0],s[1]
if a*b > 0: # ab同号
    print(abs(a+b))
else: # ab异号
  	print(max(abs(a),abs(b)))

大家的代码也可以去这里提交 🚀蜂巢

🌟 试题 F:消除游戏

题目描述

在一个字符串 S S S 中,如果 S i = S i − 1 S_i = S_i−1 Si=Si1 S i ≠ S i + 1 S_i \\ne S_i+1 Si=Si+1,则称 S i S_i Si S i + 1 S_i+1 Si+1 为边缘字符。如果且 S i ≠ S i − 1 S_i \\ne S_i-1 Si=Si1 S i = S i + 1 S_i = S_i+1 Si=Si+1,则 S i − 1 S_i−1 Si1 S i S_i Si 也称为边缘字符。其它的字符都不是边缘字符。

对于一个给定的串 S,一次操作可以一次性删除该串中的所有边缘字符(操作后可能产生新的边缘字符)。

请问经过 2 64 2^64 264 次操作后,字符串 S 变成了怎样的字符串,如果结果为空则输出 EMPTY。

输入

输入一行包含一个字符串 S 。

输出

输出一行包含一个字符串表示答案,如果结果为空则输出 EMPTY。

样例输入

edda

样例输出

EMPTY

样例输入

sdfhhhhcvhhxcxnnnnshh

样例输出

s

提示

对于 25% 的评测用例,|S | ≤ 1 0 3 10^3 103 ,其中 |S | 表示 S 的长度;

对于 50% 的评测用例,|S | ≤ 1 0 4 10^4 104

对于 75% 的评测用例,|S | ≤ 1 0 5 10^5 105

对于所有评测用例,|S | ≤ 1 0 6 10^6 106,S 中仅含小写字母。

🤔 思路

其实这道题,我当时的想法很简单,就是暴力枚举嘛,简单暴力法

不断地进行判断,所以首先就定义一个函数,这个函数就是一个操作,然后再循环迭代2的64次方次,不过这里会涉及一个判断,如果发现,进行操作后,得到的字符串和上一次的字符串一样的时候,就说明不需要再次进行操作了,这时候就直接退出,得到我们的结果。

不过提交以后发现应该只能过75%的数据,不过能拿 3/4 的分也很不错了,这时候可以想想有什么好一点的算法

💻 代码

能过75%的数据

s = input()
def f(x):
    s = set()
    for i in range(1,len(x)-1):
        if (x[i] == x[i-1] and x[i] != x[i+1]):
            s.add(i)
            s.add(i+1)
        elif (x[i] != x[i-1] and x[i] == x[i+1]):
            s.add(i-1)
            s.add(i) 
    sr = ''
    for i in range(len(x)):
        if i not in s:
            sr += x[i]
    return sr
import copy
# 2的64次方操作
for i in range(1<<64):
    pre = copy.copy(s)
    s = f(s)
    if s == '':
        print('EMPTY')
        break
    elif pre == s:
        print(s)
        break

大家的代码也可以去这里提交 🚀消除游戏

🌟 试题 G:全排列的价值

题目描述

对于一个排列 A = (a1, a2, · · · , an),定义价值 ci 为 a_1 至 a i − 1 a_i−1 ai1 中小于 a i a_i ai 的数的个数,即 bi = | a j a_j aj | j < i, a j a_j aj < a i a_i 第十三届蓝桥杯省赛b组 两道dp补题

第十三届蓝桥杯省赛b组 两道dp补题

第十三届蓝桥杯省赛C++B组 真题题解(详细讲解+代码分析)看这篇就够了~~~

第十三届蓝桥杯省赛C++B组 真题题解(详细讲解+代码分析)看这篇就够了~~~

第十三届蓝桥杯省赛 JAVA B组(真题解析+个人体会)(已更新完G题)

十三届蓝桥杯省赛C++ B组