第十四届(2023)蓝桥杯省赛python组部分真题(1)

1 棋盘:3533

1.1 题目内容

在这里插入图片描述

1.2 题目分析

  • 差分数组 + 前缀和
  • 一维差分数组:
    b[i] = a[i] - a[i - 1]
    a[i] = b[1] + … + b[i]
    a[i] = b[i] + a[i - 1]
    原地求前缀和:b[i] = b[i] + b[i - 1]
  • 给a数组[l, r]上每个数都 +c:b[l] += c, b[r + 1] -= c
  • 二维差分数组:
    a[i][j] = b[1][1] + … + b[i][j]
    b[i][j] = a[i][j] - a[i - 1][j] - a[i][j - 1] + a[i - 1][j - 1]
    原地求前缀和:b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]
  • 给a数组[x1, y1] ~ [x2, y2]上每个数都 +c:
    b[x1][y1] += c
    b[x2 + 1][y1] -= c
    b[x1][y2 + 1] -= c
    b[x2 + 1][y2 + 1] += c
  • 若操作次数为偶数,则为0;若操作次数为奇数,则为1。
  • 最后计算的前缀和即为每个点总的操作次数。

1.3 代码部分

import os
import sys

n, m = map(int, input().split())
d = [[0] * (n + 2) for _ in range(n + 2)]
for _ in range(m):
  x1, y1, x2, y2 = map(int, input().split())
  d[x1][y1] += 1
  d[x2 + 1][y1] -= 1
  d[x1][y2 + 1] -= 1
  d[x2 + 1][y2 + 1] += 1
for i in range(1, n + 1):
  for j in range(1, n + 1):
    d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1]
    if d[i][j] % 2 == 0:
      print(0, end = "")
    else:
      print(1, end = "")
  print()

2 2023:3496

2.1 题目内容

在这里插入图片描述

2.2 题目分析

  • 遍历每个数字,转换为字符串。
  • 使用str.find(“要查找的字符”,开始查找的索引位置)。
  • 结果 = 数字总数 - 包含2023的数字。

2.3 代码部分

import os
import sys
'''
ans = 0
for i in range(12345678, 98765433):
  s = str(i)
  find = s.find("2")
  if find == -1: continue
  find0 = s.find("0", find + 1)
  if find0 == -1: continue
  find2 = s.find("2", find0 + 1)
  if find2 == -1: continue
  find3 = s.find("3", find2 + 1)
  if find3 == -1: continue
  ans += 1
print(98765432 - 12345678 + 1 - ans)
'''
print(85959030)

3 硬币兑换:3501

3.1 题目内容

在这里插入图片描述

3.2 题目分析

  • 能合成的最大面值为2023 * 2 = 4046。
  • 硬币数量与硬币面值相同。
  • 枚举:第一层for循环为第一枚硬币,第二层for循环为第二枚硬币。
  • result [1 + 6] += 1,result [2 + 5] += 2,result [3 + 4] += 3,意思就是:如果所有硬币都用在7上,7最大能到多少。
  • 累加后求最大值。

3.3 代码部分

import os
import sys

result = [0] * 4047
for i in range(1, 2024):
  for j in range(i + 1, 2024):
    result[i + j] += i
print(max(result))

4 松散子序列:3543

4.1 题目内容

在这里插入图片描述

4.2 题目分析

  • 根据题意可得,子序列的每个字符在原字符串中至少隔一个字符。
  • ord(),将字母转为对应的ascii码。
  • i = 0时,计算第一个字母的价值即可。
  • i = 1时,计算前两个字母中的最大价值。
  • i = 其他时,分为两种情况:①不选 i,即dp [i - 1];②选i,即dp [i - 2] + i 的价值。

4.3 代码部分

import os
import sys

s = input()
dp = [0] * len(s)
for i in range(len(s)):
  if i == 0:
    dp[i] = ord(s[0]) - 96
  elif i == 1:
    dp[i] = max(ord(s[0]) - 96, ord(s[1]) - 96)
  else:
    dp[i] = max(dp[i - 1], dp[i - 2] + ord(s[i]) - 96)
print(dp[-1])

5 管道:3544

5.1 题目内容

在这里插入图片描述

5.2 题目分析

  • 二分法,注意left和right的范围!!!
  • 将每个水管在该时刻的水流范围排序,若当前能检测到水流的最大范围大于水管总数,则减少分钟数,否则,增大分钟数。

5.3 代码部分

import os
import sys

def check(mid):
  ans = []
  for l, s in d:
    tmp = mid - s
    if tmp >= 0:
      ans.append((l - tmp, l + tmp))
  ans.sort()
  res = ans[0][1]
  for i in range(1, len(ans)):
    if ans[i][0] - res <= 1:
      res = max(res, ans[i][1])
    else:
      break 
  return res < lens

n, lens = map(int, input().split())
d = []
for _ in range(n):
  l, s = map(int, input().split())
  d.append((l, s))
left, right = 1, 10 ** 9
while left < right:
  mid = (left + right) // 2
  if check(mid):
    left = mid + 1
  else:
    right = mid
print(left)

6 保险箱:3545

6.1 题目内容

在这里插入图片描述

6.2 题目分析

  • 动态规划,分为三种情况:直接计算、进位、退位。
  • 将数字倒置。
  • (1) 直接计算:abs(a[i] - b[i])
  • (2) 进位:10 - a[i] + b[i]
  • (3) 退位:10 + a[i] - b[i]
  • 本次进位,上次进位:10 - (a[i] + 1) + b[i],本次进位,上次退位:10 - (a[i] - 1) + b[i]
  • 本次退位,上次进位:10 + (a[i] + 1) - b[i],本次退位,上次退位:10 + (a[i] - 1) - b[i]

6.3 代码部分

import os
import sys

n = int(input())
x = list(map(int, input()))
y = list(map(int, input()))
x = [0] + x[: : -1]
y = [0] + y[: : -1]
INF = 1 << 64
dp = [[INF] * 3 for _ in range(n + 1)]
dp[1][0] = abs(x[1] - y[1])
dp[1][1] = 10 + y[1] - x[1]
dp[1][2] = 10 + x[1] - y[1]
for i in range(2, n + 1):
  dp[i][0] = min(abs(x[i] - y[i]) + dp[i - 1][0], abs(x[i] + 1 - y[i]) + dp[i - 1][1], abs(x[i] -1 - y[i]) + dp[i - 1][2])
  dp[i][1] = min(10 + y[i] - x[i] + dp[i - 1][0], 10 + y[i] - (x[i] + 1) + dp[i - 1][1], 10 + y[i] - (x[i] - 1) + dp[i - 1][2])
  dp[i][2] = min(10 + x[i] - y[i] + dp[i - 1][0], 10 + (x[i] + 1) - y[i] + dp[i - 1][1], 10 + (x[i] - 1) - y[i] + dp[i - 1][2])

print(min(dp[n][0], dp[n][1], dp[n][2]))

总结

未完待续…

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值