蓝桥《最大和》python题解

问题描述

小蓝在玩一个寻宝游戏, 游戏在一条笔直的道路上进行, 道路被分成了 n 个方格, 依次编号 1 至 n, 每个方格上都有一个宝物, 宝物的分值是一个整数 (包括正数、负数和零), 当进入一个方格时即获得方格中宝物的分值。小蓝可 以获得的总分值是他从方格中获得的分值之和。

小蓝开始时站在方格 1 上并获得了方格 1 上宝物的分值, 他要经过若干步 到达方格 n。

当小蓝站在方格 p 上时, 他可以选择跳到 p+1到 p+D(n-p) 这些方格 中的一个, 其中 D(1)=1, D(x)(x>1)定义为 x 的最小质因数。

给定每个方格中宝物的分值, 请问小蓝能获得的最大总分值是多少。

输入格式

输入的第一行包含一个正整数 n。

第二行包含 n 个整数, 依次表示每个方格中宝物的分值。

输出格式

输出一行包含一个整数, 表示答案。

样例输入

5
1 -2 -1 3 5

样例输出

8

样例输出

最优的跳跃方案为: 1→3→4→5 。

评测用例规模与约定

对于 40 % 的评测用例,1≤n≤100 。

对于 80 % 的评测用例, 1≤n≤1000 。

对于所有评测用例, 1≤n≤10000, 每个宝物的分值为绝对值不超过 10^5 的整数。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

分析:

前置知识:线性dp(可以看看洛谷的马前卒、蓝桥的数字金字塔,都是典型线性dp),欧拉筛

1. 一眼就能看出是线性dp,但是和一般的线性dp相比,这题的特殊点就是不知道每个点的前驱是什么了,要你计算出来。

2. 但是我们能从后面算前驱吗,实际上是做不到的。因为我们用p+D(n-p)时不知道p是什么,得通过循环来遍历,而且每次都要遍历,直接给时间复杂度乘上了一个n,极大影响体验

3. 那么我们不妨换一种方式,通过一层预处理来从前驱计算p+D(n-p)得到能到达的点,利用字典存在以后驱为键的键值对里

4. 这样就和普通的线性dp没什么区别了

n = int(input())
pri = []  # 存质数
s = [1 for _ in range(n + 1)]
d = [1]*(n+1)  # 直接将d给预处理,省去查找过程
for i in range(2, n + 1):  # 前面的i是数字
    if s[i]:
        pri.append(i)
        d[i] = i  # 质数的最小质因数是它本身
    for j in pri:  # 后面的i是倍数
        if i * j > n:
            break
        s[i * j] = 0
        d[i*j] = j  # 欧拉筛在筛选过程中就会产生最小质因数
        if not i % j:
            break
a = list(map(int, input().split()))
dp = [float('-inf')] * (n+1)  # 赋值-∞保证能替掉
dp[1] = a[0]
dp[2] = a[0] + a[1]
c = dict(zip(range(2, n+1), [[] for _ in range(n-1)]))
for i in range(1, n):  # 预处理前驱
    for j in range(1, d[n-i]+1):
        c[i+j].append(i)
for i in range(3, n+1):  # 线性dp
    dp[i] = max([dp[j] for j in c[i]])+a[i-1]
print(dp[n])

提示:python怎么写都不会AC,最后一个点会TLE,但是用C++尝试是可以过的,说明时间复杂度是没有任何问题的。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈子昂-北工大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值