第十三届蓝桥杯省赛C组
目录
试题A:排列字母
- 结果:AAAEEEEHHHIIILLRRRSSTTWWWY
试题B:特殊时间
- 分析:
题解
- 最后结果为:
试题C:纸张尺寸
法一、暴力
a,b=1189,841
re=[1189,841]
for i in range(1,10):
t=a
a = b
b = t // 2
re.append(a)
re.append(b)
n=str(input())
if n=='A0':
print(re[0])
print(re[1])
if n=='A1':
print(re[2])
print(re[3])
if n=='A2':
print(re[4])
print(re[5])
if n=='A3':
print(re[6])
print(re[7])
if n=='A4':
print(re[8])
print(re[9])
if n=='A5':
print(re[10])
print(re[11])
if n=='A6':
print(re[12])
print(re[13])
if n=='A7':
print(re[14])
print(re[15])
if n=='A8':
print(re[16])
print(re[17])
if n=='A9':
print(re[18])
print(re[19])
试题D:数位排序
题解
- 思路:遍历1到n+1生成数组作为键,对每个值的每一位求和作为值,先对数组的值进行升序排序,,再对数组的键进行升序排序,最后返回m-1位置的数
n=int(input())
m=int(input())
# 创建一个字典,键为数字,值为数字各位数字之和
num_sum = {}
for i in range(1, n+1):
digit_sum = sum(int(d) for d in str(i))#计算每个数字的各位数字之和
num_sum[i] = digit_sum#将数字 i 作为键,其各位数字之和作为值存储在字典 num_sum 中
# 对字典进行排序,先按值排序,再按键排序
sorted_nums = sorted(num_sum.items(), key=lambda x: (x[1], x[0]))#首先按值 x[1] 进行升序排序,如果值相同,则按键 x[0] 进行升序排序
# 输出第m-1个数字
print(sorted_nums[m-1][0])
- 92分
试题E:矩形拼接
- 见同文件夹其他文章
试题F:GCD
- 先判断a,b是否存在公倍数,存在输出0,接着a++,b++,k++,再判断ab是否存在公倍数,存在输出k,不存在继续ab++
法一
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a#最大公约数
k = 0
a, b = map(int, input().split())
while True:
if gcd(a, b) != 1: # 如果a和b有公约数,则输出0
print(0) #k=0,对a,b本身判断如果有公约数直接输出0
break
else:#当ab没有公约数
a += 1 #每次进行加1
b += 1
k += 1
if gcd(a, b) != 1: # 如果新的a和b有公约数,则输出k
print(k)
break
- 19分,大多数超出时间限制
法二
- 当a<=b时,根据更相减损术可以知道一个等式:gcd(a,b)=gcd(a,b-a);所以gcd(a+k,b+k)=gcd(a+k,b-a);设c=b-a ,想要使得a+k与c的最大公因子尽可能地大,因为最大最大能到达c ,显然这个式子的最大gcd一定为 c;只需要计算出a 最少需要增加多少可以成为 c 的倍数,这个增量即是答案k。
a, b = map(int, input().split())
if a > b:
a, b = b, a
c = b - a
g = a // c
if a % c:
g += 1
print(g * c - a)
试题G:蜂巢
- 分析
题解
dx = [0, -1, -1, 0, 1, 1] # 设置方向对应的 x,y 轴变动,例如:方向 0 的时候 x 轴不动,方向 1 的时候 y 轴 -1
dy = [-1, 0, 1, 1, 0, -1]
alist = [] # 存储两点
blist = list(map(int, input().split()))
blist = [blist[0:3], blist[3:]] # 读入数据,将输入的列表分为两个子列表,每个子列表包含三个元素,即两点的方向和移动步数
for x in range(2): # 计算两点的坐标
a, b, c = blist[x] # 获取当前点的方向和移动步数
i, j = 0, 0 # 初始化当前点的坐标为 (0, 0)
i += dx[a] * b # 根据方向和移动步数更新当前点的 x 坐标
j += dy[a] * b # 根据方向和移动步数更新当前点的 y 坐标
a = (a + 2) % 6 # 改变方向,将当前方向加 2 并取模 6,以获取下一个方向
i += dx[a] * c # 根据新的方向和移动步数更新当前点的 x 坐标
j += dy[a] * c # 根据新的方向和移动步数更新当前点的 y 坐标
alist.append([i, j]) # 将计算得到的点的坐标添加到 alist 列表中
tx = alist[1][0] - alist[0][0] # 计算 x 轴的差值
ty = alist[1][1] - alist[0][1] # 计算 y 轴的差值
if tx * ty < 0: # 如果 x 轴的差值和 y 轴的差值异号(一个正数,一个负数)
tx = abs(tx) # 将 x 轴的差值取绝对值
ty = abs(ty) # 将 y 轴的差值取绝对值
print(max(tx, ty)) # 输出 x 轴和 y 轴差值的较大值
else:
print(abs(tx) + abs(ty)) # 输出 x 轴和 y 轴差值的绝对值之和
试题H:重新排序
代码:前缀和/差分
# 定义常量 N
N = 1000005
# 定义数组 a 和 cnt,分别存储原数组的数值和每个数出现的次数
a = [0] * N
cnt = [0] * N
# 定义差分数组 diff,用来求出cnt
diff = [0] * N
# 读入 n 和原数组 a
n = int(input())
a[1:n+1] = map(int, input().split())
# 读入 m
m = int(input())
# 定义 sum1 和 sum2,分别表示原数组和最优数组的总和
sum1, sum2 = 0, 0
# 遍历所有的查询
for _ in range(m):
# 读入查询的左右端点
l, r = map(int, input().split())
# 对差分数组 diff 进行差分
diff[l] += 1
diff[r+1] -= 1
# 计算 cnt 数组
for i in range(1, n+1):
cnt[i] = cnt[i - 1] + diff[i]
# 计算原数组的总和
for i in range(1, n+1):
sum1 += a[i] * cnt[i]
# 对 a 和 cnt 数组排序(如果a和cnt都递增则结果最大;若a和cnt一个递增一个递减则结果最小)
a[1:n+1] = sorted(a[1:n+1])
cnt[1:n+1] = sorted(cnt[1:n+1])
# 计算最优数组的总和
for i in range(1, n+1):
sum2 += a[i] * cnt[i]
# 输出答案
print(sum2 - sum1)
试题I:青蛙过河
- 一只蛙,从起点到终点跳x次,再从终点到起点也是x次,可以理解为:从起点到终点跳2x次;可以进一步转化为:有2x只蛙从起点跳到终点
代码
- 未理解,下面是参考网上大家的代码
n, x = map(int, input().split()) # 读取输入的 n 和 x
a = list(map(int, input().split())) # 读取输入的数组 a
s = [0] * (n + 1) # 创建一个长度为 n+1 的数组 s,用于存储前缀和
for i in range(1, n):
s[i] = s[i - 1] + a[i] # 计算数组 a 的前缀和,存储到数组 s 中
def check(m):
for i in range(1, n - m + 1):
# 判断是否任意长度为 m 的区间都满足 >= 2x
if s[i + m - 1] - s[i - 1] < 2 * x:
return False
return True
l = 1 # 初始区间长度的最小值
r = n # 初始区间长度的最大值
while l < r:
mid = (l + r) // 2 # 计算区间长度的中间值
if check(mid):
r = mid # 如果满足条件,则将右边界更新为 mid
else:
l = mid + 1 # 如果不满足条件,则将左边界更新为 mid+1
print(l) # 输出满足条件的最小区间长度