牛客周赛 Round 40

网址:https://ac.nowcoder.com/acm/contest/80259#question
视频讲解:https://www.bilibili.com/video/BV1JT421U771/

C 题(模拟)

题目

image.png

示例

image.png

代码思路

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 题(背包问题)

题目

image.png

示例

image.png

代码思路

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 题(二分+前缀和+数学概率期望)

题目

image.png

示例

image.png

代码思路

ji
  1. 首先对数组进行排序
  2. 对于 第 i 个背包(变量说明)
    1. avg : a[i] 不拿的期望
    2. temp: a[i] 拿, 还有 n-1 个数的期望
    3. 遍历 j
      1. temp 和 a[j] 的值进行比较,如果 当前值 大于不拿的期望(temp),说明可以拿
    4. 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))
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值