Python DP 玩具购买问题

创建于:2024年9月28日

使用 OpenAI 01 预览版 回答 OpenAI01

问题

创建一个python代码,用dp算法,要求时间复杂度为logn 。小明共收到了 m 元压岁钱。商店里有10^9种玩具,种类编号为1~10^9,第i种玩具的价格为i元。但是小明已经有了其中n种玩具了,他不喜欢重复,所以每种玩具他最多只想拥有一个,已经有的就不会再买了,没有的也只会买最多一个。
现在小明想知道他最多能再买多少种玩具。
输入:第一行两个整数 n,m,表示已有玩具的种类数和压岁钱数量。
接下来一行n个整数a1,a2,.…an,表示小R拥有的所有玩具的编号。
对于所有数据,2<=n<=100000,1<=ai,m<=10^9,保证ai互不相同。
输出:输出一个整数表示小明最多能再买多少种玩具

思考

购物问题解析

选择玩具

考虑玩具价格等于ID,限制不买已有玩具。目标是用m元购买最多新玩具,可能涉及双指针或二分查找算法。

确定目标

我在分析如何在有限预算下最大化购买新的玩具,首先确定了现有的玩具列表和预算。然后,我将目标设定为找到最多的新玩具,使其价格总和不超过预算。

计算价格总和
思考如何选择新的玩具ID,提出从1开始依次检查,直到总和超过m为止。

寻找最优解

我正在寻找一个方法来确定能买到的最多数量的玩具。通过迭代未持有的ID,直到总和超过m,但避免遍历到1e9。考察从1到1e9中未在'owned'列表中的ID。

排序和处理

首先,我会对拥有的ID列表进行排序。然后,从1开始逐个处理,计算从上一个到当前拥有的ID之间的缺失ID数量。

计算缺失ID

我在计算空白ID的数量时,分别考虑了属于每个间隔内的ID数量,总和可能会很大,因此我计划通过计算不拥有ID的前k个自然数的和,直到累计和小于等于m。

寻找最小ID

确定一个函数来计算未拥有的ID到某个限制的总和,从而找到最小的ID集合,使得它们的总和不超过m。

总结遗漏身份信息

我正在计算拥有的ID之间遗漏的ID的数量和和,然后尝试找到最大数量的遗漏ID,确保它们的总和不超过m。

计算费用和缺失

我正在计算所需费用和缺失的玩具ID范围。确保总费用不超过给定预算m。

计算选择数量

我在每个间隙中计算ID的总和,然后通过二进制搜索确定可以选择的最大ID数量,确保总成本加上中间ID和仍不超过m。

编写代码进行计算

我正在写代码来计算每个间隙的14,考虑到间隙数量和每个间隙大小。这让我想到了优化时间复杂性的可能性。

找最大K值

设定总成本和总玩具数,找到最多可以购买的玩具数量。使用二维动态规划,并考虑最优组合选择,确保不超过预算。

仔细计算和优化排序

我在编纂算法时,确保使用64位整数以处理整数溢出。而且,时间复杂度是O(n * log N),符合要求。

排序与初始化

我正在对拥有的ID列表进行排序,初始化总成本和总玩具数,然后逐个ID 进行处理,计算每个间隙的最大k值,并通过二分法找到满足条件的最大k,更新总玩具数和总成本。

寻求更高利润的库存

我正在评估库存的情况,并寻找可能的利润增长点。这个旅程让我充满了动力和好奇心。

整理并计算

回答

下面是满足要求的Python代码,使用二分查找算法,时间复杂度为O(n log N),其中n是已有玩具的数量,N是玩具编号的最大值(10^9)。

n, m = map(int, input().split()) owned = list(map(int, input().split())) owned.sort() def compute_sum_k(s, k): return k * s + k * (k - 1) // 2 def max_toys_in_gap(s, gap_size, total_cost, m): left = 0 right = gap_size while left < right: mid = (left + right + 1) // 2 sum_k = mid * s + mid * (mid - 1) // 2 if total_cost + sum_k <= m: left = mid else: right = mid - 1 return left total_toys = 0 total_cost = 0 prev_owned = 0 N = 10**9 for curr_owned in owned + [N + 1]: s = prev_owned + 1 e = min(curr_owned - 1, N) gap_size = e - s + 1 if gap_size <= 0 or total_cost >= m: prev_owned = curr_owned continue k = max_toys_in_gap(s, gap_size, total_cost, m) if k > 0: total_toys += k total_cost += compute_sum_k(s, k) prev_owned = curr_owned print(total_toys)

分享这个问答