D
🦐头题。本质就是划分子集,纯暴力。但其实没那么暴力,你得想到加来加去就相当于分成几堆,因为0^X=X,所以零对异或没影响。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
N = int(input()) # 袋子数量
A = list(map(int, input().split())) # 每个石头的数量
ans = set() # 存储所有可能的异或和
def dfs(pos, B):
# 所有石头都处理完毕时
if pos == N:
x = 0
for b in B:
x ^= b # 计算当前状态的异或和
ans.add(x)
return
# 方案1: 将当前石头放入已有的袋子
for i in range(len(B)):
B[i] += A[pos] # 加入当前石头
dfs(pos + 1, B) # 递归处理下一个石头
B[i] -= A[pos] # 回溯还原
# 方案2: 放入新袋子
dfs(pos + 1, B + [A[pos]]) # 创建新袋子存放当前石头
dfs(0, []) # 从空状态开始搜索
print(len(ans)) # 输出不同异或和的数量
|
E
一眼dp。题解的背包什么玩意看不明白为啥又来了一个遍max,还是记录一下自己的。就是三个01背包,然后再枚举等于k的情况,复杂度完全够用。
1
2
3
4
5
6
7
|
# dp[c] = 在热量 c 内能获得的最大维生素值
def build_dp(arr):
dp = [0]*(X+1)
for (val, cal) in arr:
for c in range(X, cal-1, -1):
dp[c] = max(dp[c], dp[c-cal] + val)
return dp
|
然后我们就得到了三个背包的dp数组。X最大是5000,两层循环暴力直接过!
1
2
3
4
5
6
7
|
ans = 0
for i in range(1, X+1):
for j in range(1, X+1):
k = X - i - j
if k < 0:
break
ans = max(ans, min(dp1[i], dp2[j], dp3[k]))
|