文章目录
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]))
总结
未完待续…