第一题
- 子集
from math import inf
from re import A
import sys
from bisect import bisect_right
from collections import defaultdict
input = lambda: sys.stdin.readline().rstrip("\r\n")
def I():
return input()
def II():
return int(input())
def MI():
return map(int, input().split())
def LI():
return list(input().split())
def LII():
return list(map(int, input().split()))
def GMI():
return map(lambda x: int(x) - 1, input().split())
def LGMI():
return list(map(lambda x: int(x) - 1, input().split()))
def solve():
n = II()
xs, ys = LII(), LII()
d = [[x, y] for x, y in zip(xs, ys)]
lst = sorted(d, key = lambda x: (x[0], -x[1]))
def lengthOfLIS(nums):
# lis
# 二分 + 贪心
# D[i]表示长度为i时最小的lis结尾元素
D = []
for num in nums:
index = bisect_right(D, num)
# 第一个先加进来
if len(D) == 0:
D.append(num)
continue
# 相等的话不能要
if index <= len(D) and D[index - 1] == num:
continue
if index == len(D):
D.append(num)
else:
D[index] = num
#print(D)
return len(D)
print(lengthOfLIS([y for _, y in lst]))
if __name__ == '__main__':
for _ in range(II()):
solve()
- 这道题显然是LIS和排序,难点是如何对于同一个x只选一个y
- 这个只需要先对x顺序排序,再对y倒序排序,然后从y的集合中选lis(严格的)
- 这既保证了一个x对应的ys中最多只能选一个,又保证了选出来的y是严格递增的
第二题
- 小强爱数学
import sys
input = lambda: sys.stdin.readline().rstrip("\r\n")
def I():
return input()
def II():
return int(input())
def MI():
return map(int, input().split())
def LI():
return list(input().split())
def LII():
return list(map(int, input().split()))
def GMI():
return map(lambda x: int(x) - 1, input().split())
def LGMI():
return list(map(lambda x: int(x) - 1, input().split()))
def solve():
a, b, n = LII()
MOD = 10 ** 9 + 7
if n == 1:
print(a)
if n == 2:
print((a * a - 2 * b) % MOD)
dp = [0] * n
dp[0] = a
dp[1] = (a * a - 2 * b) % MOD
for i in range(2, n):
dp[i] = dp[i - 1] * a - b * dp[i - 2]
dp[i] %= MOD
print(dp[-1])
if __name__ == "__main__":
for _ in range(II()):
solve()
- 找到递归公式进行dp即可
- dp[i] = dp[i - 1] * a - dp[i - 2] * b
第三题
- 二叉树
import sys
input = lambda: sys.stdin.readline().rstrip("\r\n")
def I():
return input()
def II():
return int(input())
def MI():
return map(int, input().split())
def LI():
return list(input().split())
def LII():
return list(map(int, input().split()))
def GMI():
return map(lambda x: int(x) - 1, input().split())
def LGMI():
return list(map(lambda x: int(x) - 1, input().split()))
MOD = 10 ** 9 + 7
def solve():
n, m = LII()
# dp[i][j]: 节点个数为i且高度小于等于j的方案数
dp = [[0 for _ in range(m + 1)] for _ in range(n + 1)]
for j in range(m + 1):
dp[0][j] = 1
for i in range(1, n + 1):
for j in range(1, m + 1):
# 考虑左右子树
for k in range(i):
tmp = (dp[k][j - 1] * dp[i - 1 - k][j - 1]) % MOD
dp[i][j] += tmp
dp[i][j] %= MOD
print(dp[-1][-1])
if __name__ == "__main__":
for _ in range(1):
solve()
- dp[i][j]表示节点个数为i,高度不超过j的总方案数
- 经典树形dp
- 固定一个根,然后节点个数两边分配k,高度的话就是j - 1以内即可
- 这个数也叫做卡特兰数
第四题
- 对称飞行器
from heapq import heapify, heappop, heappush
from math import inf
import sys
from collections import defaultdict, deque
input = lambda: sys.stdin.readline().rstrip("\r\n")
def I():
return input()
def II():
return int(input())
def MI():
return map(int, input().split())
def LI():
return list(input().split())
def LII():
return list(map(int, input().split()))
def GMI():
return map(lambda x: int(x) - 1, input().split())
def LGMI():
return list(map(lambda x: int(x) - 1, input().split()))
def solve():
n, m = LII()
grid = []
for _ in range(n):
grid.append(I())
d = defaultdict(lambda: inf) # (x, y, t) -> minn
sx, sy = -1, -1
ex, ey = -1, -1
for i in range(n):
for j in range(m):
if grid[i][j] == 'S':
sx, sy = i, j
if grid[i][j] == 'E':
ex, ey = i, j
d[(sx, sy, 0)] = 0
dq = deque([]) # (step, x, y, t)
dq.append((0, sx, sy, 0))
#heappush(pq, (0, sx, sy, 0))
while dq:
#print(pq)
step, x, y, t = dq.popleft()
if x == ex and y == ey:
print(step)
return
# 四周的点
for nx, ny in ((x + 1, y), (x - 1, y), (x, y - 1), (x, y + 1)):
if 0 <= nx < n and 0 <= ny < m and grid[nx][ny] != '#':
if d[(nx, ny, t)] <= step + 1:
continue
d[(nx, ny, t)] = step + 1
#heappush(pq, (step + 1, nx, ny, t))
dq.append((step + 1, nx, ny, t))
# 对称点
ox, oy = n - x - 1, m - y - 1
if grid[ox][oy] != '#' and t < 5 and d[(ox, oy, t + 1)] > step + 1:
d[(ox, oy, t + 1)] = step + 1
#heappush(pq, (step + 1, ox, oy, t + 1))
dq.append((step + 1, ox, oy, t + 1))
print(-1)
if __name__ == "__main__":
for _ in range(1):
solve()
- 用x, y,t记录状态,每个状态有一个最小的到达时间
- 用d记录最小到达时间,dq直接就是最小的,这里不需要pq做额外的操作
第五题
- 知识竞赛
import sys
input = lambda: sys.stdin.readline().rstrip("\r\n")
def I():
return input()
def II():
return int(input())
def MI():
return map(int, input().split())
def LI():
return list(input().split())
def LII():
return list(map(int, input().split()))
def GMI():
return map(lambda x: int(x) - 1, input().split())
def LGMI():
return list(map(lambda x: int(x) - 1, input().split()))
def solve():
n = II()
vs = []
for _ in range(n):
vs.append(LII())
# 思维题, 按abs(a - b)排好后,i < j, 则j的a和b大小就可以决定最终的答案
# 比如j的bj < aj,那么它和前面的组合最小值一定是b, 这时只要找到前面最大的b即可
# 对于i而言
# 若bi < ai, 显然btot < atot
# 若bi > ai, 由于j的差值更大,所以bj会拉小得更厉害,所以还是又btot < atot
vs.sort(key = lambda x: abs(x[0] - x[1]))
ans = 0
amax, bmax = vs[0]
for j in range(1, n):
a, b = vs[j]
cur = 0
if a < b:
cur = (a + amax) / 2
else:
cur = (b + bmax) / 2
ans = max(ans, cur)
amax = max(a, amax)
bmax = max(b, bmax)
print(ans)
if __name__ == "__main__":
for _ in range(1):
solve()
- 为了避免较差得能力要同时受两个人的影响
- 我们可以根据abs(a - b)进行排序
- 比如j的bj < aj,那么它和前面的组合最小值一定是b, 这时只要找到前面最大的b即可
- 对于i而言
- 若bi < ai, 显然btot < atot
- 若bi > ai, 由于j的差值更大,所以bj会拉小得更厉害,所以还是又btot < atot
总结
思维、dp、搜索的全面考核啊。。。