最少操作次数计算

創建於:2025年2月2日

使用 O3 Mini 回答 Chat01

問題

用python写程序

给你两个数组 nums 和 target 。
在一次操作中,你可以将 nums 中的任意一个元素递增 1 。
返回要使 target 中的每个元素在 nums 中 至少 存在一个倍数所需的 最少操作次数 。

示例 1:
输入:nums = [1,2,3], target = [4]
输出:1
解释:满足题目条件的最少操作次数是 1 。
将 3 增加到 4 ,需要 1 次操作,4 是目标值 4 的倍数。

示例 2:
输入:nums = [8,4], target = [10,5]
输出:2
解释:满足题目条件的最少操作次数是 2 。
将 8 增加到 10 ,需要 2 次操作,10 是目标值 5 和 10 的倍数。

示例 3:
输入:nums = [7,9,10], target = [7]
输出:0
解释:
数组中已经包含目标值 7 的一个倍数,不需要执行任何额外操作。

示例 4:
输入:nums = [7,9,10], target = [427]
输出:417

提示:
1 <= nums.length <= 5 * 10^4
1 <= target.length <= 4
target.length <= nums.length
1 <= nums[i], target[i] <= 10^4

思考

Understanding the problem

I’m examining the issue of ensuring that each element in the target array has at least one multiple in the nums array through the minimal number of increments.

Mapping out efficiency

I'm thinking through the idea that a single increment to an element can fulfill multiple target elements, aiming for the fewest total increments needed to meet the condition.

Focusing on the small target

Considering the small size of the target array, I'm working on selecting nums elements to update, ensuring they are multiples of target elements, aiming to minimize the sum of increments.

Sorting and cost minimization

I'm organizing the target elements. The goal is to update nums elements to multiples of target elements, aiming to minimize the total increment cost by selecting a minimal cost subset.

Mapping the cost

I’m assigning nums elements to cover specific subsets of target elements, aiming to minimize the total increment cost by calculating minimal costs for each subset and ensuring every target is covered.

Evaluating nonempty subsets

I'm determining the minimal cost to update each nums element, ensuring it can cover each target in a nonempty subset by considering potential zero-cost updates and additional costs for covering more targets.

Calculating update costs

OK, let me see. I'm figuring out the minimal cost to adjust nums elements so they can cover all targets in each nonempty subset, using the least common multiple (LCM) of the subset's targets.

Tracking target coverage

I'm piecing together how multiples of LCM cover larger sets than just the subset S, leading to a bitmask of covered targets that might include additional elements not originally in S.

Charting coverage

I'm figuring out how to compute the bitmask for covered targets given a candidate value v. It should cover the subset S and possibly more targets due to the LCM constraints.

Strategizing cost efficiency

I’m thinking about a dynamic programming approach to minimize update costs, aiming to cover all target bits with optimal subsets of elements, each updated exactly once.

Crafting a cost-effective strategy

I'm piecing together an independent element update strategy to minimize total costs, ensuring each target bit is covered through optimal combinations of elements and their respective costs.

Evaluating update options

OK, I'm looking at dynamic programming to budget update costs for each target bit. We'll select the best candidate from each element, ensuring precise coverage and cost minimization.

Managing elements

Each element update is unique, so the DP method treats them as distinct. Considering constraints, the method effectively manages up to 750k elements.

Mapping solutions

I'm examining strategies like dictionaries or C++ for optimization, given the constraints. The aim is to precompute or combine elements efficiently to minimize operations.

Refining the process

I'm thinking about precomputing lcms for subsets and iterating over elements to calculate candidate costs, effectively using a dynamic programming algorithm to handle up to 750k iterations in Python.

Mapping out DP updates

I'm working through updating dynamic programming over 50k items with each element holding up to 15 candidate options. Each element can only be chosen once, aiming to minimize costs.

Evaluating feasibility

Determining if 800k iterations are manageable in Python, especially with PyPy. The algorithm is optimized to compute minimal update costs for each element and mask, considering constraints and feasibilities.

Evaluating alternative strategies

Considering a greedy approach to minimize costs by adjusting elements to be multiples of targets, while managing intersections effectively. This might lead to a more efficient solution.

Precomputing and combining

I’m considering precomputing minimal costs for each candidate mask and combining these. Handling constraints like disallowing choosing two different candidates from the same element element.

Mapping combinations

I’m focusing on combining 1 to 4 candidate updates, each having a bitmask and cost, to cover the full mask efficiently and ensure each element is uniquely included.

Balancing distinct choices

I’m balancing the need for unique indices and minimizing costs by evaluating various combinations of candidate mask updates to ensure every bit in the full mask is covered efficiently.

Strategizing updates

Utilizing dynamic programming to manage candidate updates, distinct indices, and minimize costs, while efficiently covering all elements in the mask.

Crafting intricate strategies

I'm piecing together a multi-stage dynamic programming approach, leveraging bit masks and distinct indices to optimize coverage and cost, though navigating the vast number of items remains a challenge.

Navigating efficiency

I’m mapping out a dynamic programming approach with a 16-state dictionary, leveraging the small value of 'm' to iterate over each element and efficiently update the new_dp values.

Precomputing element costs

I'm piecing together the possibility of precomputing an element's best candidate cost for each mask, ensuring efficient handling of distinct candidate masks in the dynamic programming approach.

Navigating LCM calculations

Precomputing the best candidate mask for each element with distinct indices requires LCM calculations to efficiently cover all elements in the mask. The bitmask update strategy is employed.

Refining the strategy

I’m combining elements with candidate masks using 0/1 knapsack dynamic programming, iterating over 50k elements and 240 options per element, to find the least costly solution.

Exploring vectorized updates

I'm thinking through how vectorized dynamic programming updates can efficiently handle the 16 states, potentially optimizing performance by combining elements and masks in a single loop.

Precomputing candidates

I’m analyzing the feasibility of precomputing candidate mask pairs for each element, aiming to enhance Python code performance by streamlining the inner loop iterations within the dynamic programming approach.

Integrating candidate updates

I’m working through grouping candidate updates by element to streamline inner loops in Python, using local variables and potentially PyPy for optimization.

Calculating iteration cost

I’m determining the time for 12 million iterations in Python, factoring in loop performance and PyPy optimization, to understand feasibility and potential delays.

Precomputing and combining

I’m thinking through using precomputation to determine the best candidate update per element, ensuring each mask outcome is combined efficiently with a straightforward dynamic programming update over a 16-length dp array.

Optimizing with precomputation

I’m looking into precomputing candidate update options for each element, simplifying the dynamic programming update by iterating efficiently through a list of masks and costs.

Optimizing dynamic programming

I’m exploring efficient loop techniques in C and PyPy, including precomputing candidate subsets and iterating through states and elements to minimize DP state updates for each mask and cost.

Refining the approach

I’m combining bitmask calculations and updating a dynamic programming array. Each element has a unique subset of masks, ensuring minimal cost accumulation without the order mattering.

Ensuring accurate updates

I’m iterating through dynamic programming states in descending order to ensure each element is used once, efficiently updating combinations to minimize overall cost.

Updating efficiently

I’m iterating through states with a temporary dp array, ensuring each element is updated once only, aiming to minimize the overall cost while avoiding double usage of any element.

Assessing performance feasibility

I’m realizing that performing 50 million iterations per second in Python might be feasible, especially on platforms like PyPy, where it could take around 1.2 seconds in pure Python loops.

Assessing iteration feasibility

I’m mapping out Python's iteration capabilities, ensuring 12 million iterations per second is achievable, especially in CP Python, given the target length and candidate subsets.

Optimizing strategies

I'm working on a plan to precompute candidate subsets for target indices and explore sorting suggestions for efficient DP updates, aiming for an efficient and streamlined approach.

Mapping progress

I’m combining steps to map minimal costs to resulting masks, precomputing LCMs for target subsets, and refining candidate info for efficient DP updates and cost calculations.

Streamlining DP updates

I’m detailing a method to iterate over target numbers and efficiently set bits. Updating the dp array involves iterating over candidate masks and states, optimizing for minimal costs.

Processing specific elements

I'm thinking through candidate costs and masks to update the dp array for each element, ensuring efficient states and minimal costs. Progress is steady and promising.

Confirming results

OK, let me see. I’m checking the dp array updates for each element, ensuring minimal costs and states, which leads to having the correct final answer for Example 2.

Piecing together costs

I'm mapping out the costs and supported masks for each candidate subset of elements 8 and 4, refining the candidate dictionary with the corresponding costs and resulting masks.

Mapping dp updates

I’m thinking through dp array updates for each element and candidate subset, ensuring efficient states and minimal costs, aligned with the target set. This leads me to a more optimized approach.

Thought about minimum operations for multiples 持续 55 秒

回答

下面给出一种 Python 解法,思路是:

  1. 对于每个目标数 tt ,我们希望在数组 nums 中至少有一个数(经过若干次“+1”操作后)能变成 tt 的倍数。
  2. 由于一个数经过更新后得到的值 vv ,如果满足 vmodt=0v \bmod t=0 ,那么这个数可以“覆盖”目标 tt;而一个数更新后的值可能同时满足多个 tt 的条件。
  3. 因为 target 数组长度最多 4,我们可以用一个 4 位的二进制掩码表示哪些目标已“被覆盖”。最终要求掩码为 (1<<m)1 (1<<m)-1(全部 1)。
  4. 对于每个 nums 中的数 xx ,我们可以考虑“将其更新为一个恰好能覆盖某个子集 SSSS\subseteq target)的倍数”的方案。
    • L=lcm({t:tS})L = \mathrm{lcm}(\{t: t\in S\}) ,则将 xx 更新为不小于 xx 的最小 LL 的倍数: v=xL×L,v = \left\lceil \frac{x}{L} \right\rceil \times L, 操作次数为 vxv-x
    • 更新后的 vv 不仅必定是 SS 中所有目标的倍数,而且可能正好是 target 中更多目标的倍数;我们扫描 target 得到“实际覆盖”子集(记为一个二进制掩码)。
  5. 每个元素最多只能使用一次。令 dp[mask] 表示“经过若干个(若干个 nums 元素各选一种更新方案)的选择后,能使得覆盖状态达到 mask 所需的最少操作数”。初始 dp[0]=0,其它 dp[mask]=∞。
  6. 对于 nums 中的每个数,我们枚举它所有的候选更新方案,然后用 0/1 背包的思想更新 dp。最后答案即 dp[ FULL ] ,其中 FULL=(1<<m)1 FULL = (1<<m)-1

下面是完整代码(注意:输入格式假设两行分别给出 nums 和 target,形如 [1,2,3]):


python
import sys import math import re def solve(): data = sys.stdin.read().strip() if not data: return # 从输入中提取两个列表(形如 "[1,2,3]" 和 "[4]") lists = re.findall(r'$$([^$$]*)\]', data) if len(lists) < 2: return def parse_list(s): s = s.strip() if not s: return [] return list(map(int, s.split(','))) nums = parse_list(lists[0]) target = parse_list(lists[1]) m = len(target) FULL = (1 << m) - 1 # 预计算所有非空子集(target 的下标集合)的 lcm # 因为 target 长度最多 4,非空子集最多 2^4 - 1 = 15 个 cand_info = [] # 每项为 (mask, L) ,mask 表示选取了哪些 target ,L 为 lcm def lcm(a, b): return a // math.gcd(a, b) * b for mask in range(1, 1 << m): L = 1 for j in range(m): if mask & (1 << j): L = lcm(L, target[j]) cand_info.append((mask, L)) INF = 10**18 # dp[mask] = 最少操作次数使得已经选中的元素覆盖状态为 mask dp = [0] + [INF] * FULL # 对于 nums 中的每个元素,计算它的候选更新方案。 # 注意:每个元素只能更新一次,所以我们对每个元素构造一个“候选方案集合” for x in nums: # 对于一个元素,可以枚举所有非空候选子集, # 计算 v = ceil(x / L) * L, cost = v - x # 然后扫描 target 数组,判断 v 能覆盖哪些目标(即 v % t == 0),得到一个掩码 cand_mask best = {} # best[cand_mask] = 在本元素中选取方案使得覆盖状态为 cand_mask 的最小 cost for _, L in cand_info: # 更新到不小于 x 的最小 L 的倍数 v = ((x + L - 1) // L) * L cost = v - x # 计算 v 能覆盖哪些 target cand_mask = 0 for j in range(m): if v % target[j] == 0: cand_mask |= (1 << j) # 更新最小 cost if cand_mask in best: if cost < best[cand_mask]: best[cand_mask] = cost else: best[cand_mask] = cost # 0/1 背包更新:对于本元素的每个候选方案, # 对于已有的 dp 状态 state,更新 dp[state | cand_mask] newdp = dp[:] # 新 dp 状态:不使用本元素的情况仍保留 for cand_mask, cand_cost in best.items(): # 这里遍历 dp 的 16 个状态(m<=4,所以最多 16 个) for prev_mask in range(FULL + 1): if dp[prev_mask] == INF: continue new_mask = prev_mask | cand_mask new_cost = dp[prev_mask] + cand_cost if new_cost < newdp[new_mask]: newdp[new_mask] = new_cost dp = newdp # 输出答案 sys.stdout.write(str(dp[FULL])) if __name__ == '__main__': solve()

说明

  • 预处理候选子集
    我们枚举 target 所有非空子集,计算对应的 lcm。这样对于一个元素 xx ,可以用公式

    v=xL×Lv = \left\lceil \frac{x}{L} \right\rceil \times L

    得到更新后值,再计算更新次数(vxv-x)。

  • 计算“实际覆盖”
    虽然我们是根据某个子集更新的,但更新后的数 vv 可能同时满足更多 tt 的倍数条件,因此遍历 target 数组计算最终覆盖掩码。

  • 动态规划更新
    用 dp 数组记录:使用部分元素后能覆盖哪些目标,以及对应的最少操作次数。每个元素只能用一次,因此更新时需要基于旧的 dp 状态。

此解法的时间复杂度大约为

O(n2mm)O(n \cdot 2^m \cdot m)

由于 m4m\le4 ,即使 nn 达到 5×1045\times 10^4 也足够。

你可以直接运行以上代码来解决问题。

分享這個問答