
本文介绍如何在 O(log n) 时间内求解有序向量 V = ⟨v₁, …, vₙ⟩(其中 vᵢ = 5×i)中,最多可选取多少个互异元素,使其总和 ≤ M;核心在于利用等差数列求和公式与二分搜索,避免线性扫描。
本文介绍如何在 o(log n) 时间内求解有序向量 v = ⟨v₁, …, vₙ⟩(其中 vᵢ = 5×i)中,最多可选取多少个**互异元素**,使其总和 ≤ m;核心在于利用等差数列求和公式与二分搜索,避免线性扫描。
该问题表面是“背包式选择”,实则具有强结构约束:向量 V 的元素严格按索引线性增长(vᵢ = 5i),且题目要求选取尽可能多的元素(而非最大化价值),而元素已天然有序——最小的元素排在最前(v₁=5, v₂=10, …)。因此,贪心策略最优:总是优先选最小的未选元素。即,最优解必为前 k 个元素 {v₁, v₂, ..., vₖ},因为任何跳过小元素而选更大元素的方案,都会在相同数量下导致和更大,或在相同和限制下容纳更少元素。
于是问题转化为:求最大整数 k(0 ≤ k ≤ n),使得
[
\sum_{i=1}^{k} vi = \sum{i=1}^{k} 5i = 5 \cdot \frac{k(k+1)}{2} \leq M
]
注意:题目示例中 V = [0, 5, 10, 15, 20] 包含 v₀ = 0(对应 i=0),但题干定义为 V = ⟨v₁,…,vₙ⟩ 且 vᵢ = 5×i,故标准形式应从 i=1 开始。若实际输入含 v₀=0,则它可无条件加入(不增加和),最终答案需额外 +1 —— 这正是示例末尾 +1 的由来。
解法一:数学闭式解(O(1),满足 O(log n) 要求)
将不等式变形:
[
5 \cdot \frac{k(k+1)}{2} \leq M \quad \Rightarrow \quad k^2 + k - \frac{2M}{5} \leq 0
]
解二次方程 (k^2 + k - \frac{2M}{5} = 0),正根为:
[
k = \left\lfloor \frac{-1 + \sqrt{1 + \frac{8M}{5}}}{2} \right\rfloor
]
该解即为满足条件的最大 k(从 1 开始计数)。若向量包含 v₀=0,则总可选数为 k + 1(0 永远免费)。
import math
def max_items_closed_form(M, n):
if M <h3>解法二:二分搜索(严格 O(log n))</h3><p>当无法使用浮点运算或需规避精度误差时,可在范围 [0, n] 上对 k 进行二分搜索,每次验证前 k 项和是否 ≤ M:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/ai/3679" title="畅图AI"><img
src="https://img.php.cn/upload/ai_manual/001/246/273/178599564049124.png" alt="畅图AI" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/ai/3679" title="畅图AI" class="overflowclass">畅图AI</a>
<p class="overflowclass">畅图AI是一款AI思维导图工具,AI图表生成工具,一键生成思维导图、流程图。</p>
</div>
<a rel="nofollow" href="/ai/3679" title="畅图AI" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><pre class="brush:php;toolbar:false;">def max_items_binary_search(M, n):
def prefix_sum(k):
# sum(v1..vk) = 5 * k * (k+1) // 2
return 5 * k * (k + 1) // 2
left, right = 0, n
result = 0
while left <h3>注意事项与总结</h3>
- 时间复杂度:两种方法均为 O(1) 或 O(log n),远优于暴力 O(n);
- 边界处理:当 M
- 索引一致性:务必确认输入向量是否含 v₀=0;若 V 严格为 ⟨v₁,…,vₙ⟩(无零),则答案直接为 k,无需 +1;
- 数值溢出:对极大 M,k*(k+1) 可能溢出,建议使用 Python 的任意精度整数或转为浮点计算(闭式法);
- 通用性:本解法依赖 vᵢ = c·i 的线性结构;若模式变化(如 vᵢ = i²),需重新建模。
综上,抓住“贪心取前缀”本质,结合等差数列求和与二分/解析解,即可优雅实现 O(log n) 最优解。










