网址:https://ac.nowcoder.com/acm/contest/80259#question
视频讲解:https://www.bilibili.com/video/BV1JT421U771/
C 题(模拟)
题目
示例
代码思路
from collections import defaultdict
def fill(nums):
n = len(nums)
st = set(nums)
idx = [i for i,num in enumerate(nums) if num == 0]
for num in range(1,n+1):
if num not in st:
nums[idx.pop()] = num
def construct_permutations(n,a):
counts = defaultdict(list)
# key存储a的值,value存储的是下标
p = [0] * n
q = [0] * n
for i in range(n):
counts[a[i]].append(i)
if len(counts[a[i]])>2:
return -1
# 主要处理0,1,2次的情况
# 先处理次数为2的情况
for k,v in counts.items():
if len(v) == 2:
p[v[0]] = k
q[v[1]] = k
# 再处理出现1的
for k,v in counts.items():
if len(v) == 1:
p[v[0]] = k
q[v[0]] = k
# 最后存储的是0次的
fill(p)
fill(q)
return p,q
#示例输入
n = int(input())
a = list(map(int,input().split()))
#调用函数构造排列
result = construct_permutations(n,a)
#输出结果
if result == -1:
print(-1)
else:
p,q = result
print(' '.join(str (x) for x in p))
print(' '.join(str (x) for x in q))
D 题(背包问题)
题目
示例
代码思路
n,x = map(int,input().split()) #输入装备数量和小红拥有的金币
max_power = 0 # 最大战力初始值为0
nums = [[] for _ in range(n)] #装备列表
# 分别代表装备初始战力,购买该装备需要的金币、升1级花费的金币
# 升1级提升的战力、最高可以提升的等级。
for i in range(n):
att,price,cost,upgrade,lvmax = map(int,input().split())
#计算小红购买并强化当前装备的最大战力
for level in range(lvmax+1):
p = price + cost * level
a = att + upgrade * level
if p <= x:# 如果拥有足够的金币购买装备
nums[i].append((p,a)) #更新()
else:
break #金币不足以购买当前装备,跳出循环
for i in range(n):
nums[i].sort() #价格从小达到大
# 用多重背包去解决这个问题,拥有x金币,购买装备的最大战力.
dp = [0] * (x + 1) # dp[i]表示拥有i金币时的最大战力
for i in range(n):
for j in range(x, -1, -1):
for p, a in nums[i]:
if j >= p:
dp[j] = max(dp[j], dp[j - p] + a)
else:
break
max_power = dp[x] # 最大战力为拥有x金币时的最大战力
print(max_power)
F 题(二分+前缀和+数学概率期望)
题目
示例
代码思路
j | i |
---|
- 首先对数组进行排序
- 对于 第 i 个背包(变量说明)
avg
: a[i] 不拿的期望temp
: a[i] 拿, 还有 n-1 个数的期望- 遍历 j
- temp 和 a[j] 的值进行比较,如果 当前值 大于不拿的期望(temp),说明可以拿
E
:a[i] 拿的期望
代码实现
n = int(input())
a = list(map(int,input().split()))
if n<= 2:
print(sum(a))
exit()
# avg:a[i]不拿的期望
# 期望:sum(所有的情况)//(有多少种情况)
s = sum(a)
# avg = (n-1)*s/((n-1)*n*2)
avg = s*2/n
res = 0
for i in range(n):
#已经选择a[i],再从剩下选择一个
temp = (s - a[i])/(n-1)
E = 0
for j in range(n):
if i!=j:
E += max(a[j],temp)
E /= (n-1)
res += max(avg,E+a[i])
print("%.7f" %(res/n))
from bisect import bisect_right
n = int(input())
a = list(map(int,input().split()))
a.sort()
if n<= 2:
print(sum(a))
exit()
# avg:a[i]不拿的期望
# 期望:sum(所有的情况)//(有多少种情况)
s = sum(a)
# avg = (n-1)*s/((n-1)*n*2)
avg = s*2/n
res = 0
sm = [0] *(n+1)
for i in range(n-1,-1,-1):
sm[i] = a[i] + sm[i+1]
for i in range(n):
#已经选择a[i],再从剩下选择一个
temp = (s - a[i])/(n-1)
id = bisect_right(a,temp)
E = sm[id] + temp * (id)
if a[i]>= temp:
E -= a[i]
else:
E -= temp
E /= (n-1)
res += max(avg,E+a[i])
print("%.7f" %(res/n))