
本文详解如何通过合理排列数组元素,使定义的“数组商”(即总和除以前缀和的向下取整之和)达到最大值,并指出常见实现错误及正确解法。
本文详解如何通过合理排列数组元素,使定义的“数组商”(即总和除以前缀和的向下取整之和)达到最大值,并指出常见实现错误及正确解法。
在本题中,“数组商”并非数学意义上的商,而是一个特定构造的累加量:给定数组 $ A $,设其总和为 $ X = \sum_{i=1}^N A_i $,前缀和数组 $ \text{pre}[i] = A_1 + A_2 + \dots + A_i $(1-indexed),则数组商定义为:
$$ \text{Quotient}(A) = \sum_{i=1}^{N} \left\lfloor \frac{X}{\text{pre}[i]} \right\rfloor $$
关键洞察在于:要使该和最大,应让前缀和增长尽可能缓慢——因为 $ \left\lfloor \frac{X}{\text{pre}[i]} \right\rfloor $ 随 $ \text{pre}[i] $ 增大而单调递减,且下降非线性(分母越小,贡献越大)。因此,将较小的元素置于前面,使前缀和初期尽量小,可显著提升早期项的值。
✅ 正确策略:升序排列数组(即 arr.sort((a,b) => a - b))。
例如样例 [1, 1, 3]:
- 升序后仍为 [1, 1, 3]
- 前缀和 pre = [1, 2, 5],总和 $ X = 5 $
- 商 = $ \lfloor5/1\rfloor + \lfloor5/2\rfloor + \lfloor5/5\rfloor = 5 + 2 + 1 = 8 $
❌ 原错误代码问题分析:
let quotient = pre[i] * (i + 1) + (pre[n - 1] - pre[i]);
该行完全偏离题意——它既未计算 $ \lfloor X / \text{pre}[i] \rfloor $,也未累加,而是错误地构造了一个无意义的表达式(导致输出 15)。这是典型的逻辑误写,混淆了问题定义与自创公式。
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
✅ 正确实现要点:
- 先升序排序(贪心基础);
- 构建前缀和数组;
- 遍历每个前缀和,累加 Math.floor(X / pre[i])(注意:JS 中 parseInt(x/y) 在正数场景等价于 Math.floor,但语义更清晰推荐 Math.floor);
- 时间复杂度 $ O(N \log N) $,空间 $ O(N) $,满足 $ N \leq 10^5 $ 约束。
以下是健壮、可读的参考实现:
function maxQuotient(n, arr) {
// 升序排序:最小元素优先,压低前缀和增长速度
arr.sort((a, b) => a - b);
// 构建前缀和
const pre = new Array(n);
pre[0] = arr[0];
for (let i = 1; i < n; i++) {
pre[i] = pre[i - 1] + arr[i];
}
const X = pre[n - 1]; // 总和
// 累加 floor(X / pre[i])
let result = 0;
for (let i = 0; i < n; i++) {
result += Math.floor(X / pre[i]);
}
return result;
}
// 示例调用
console.log(maxQuotient(3, [1, 1, 3])); // 输出: 8⚠️ 注意事项:
- 所有元素均为正整数(约束 Ai ≥ 1),故前缀和严格递增且无零除风险;
- 不可降序排列——例如 [3,1,1] 得 pre=[3,4,5],商为 $ \lfloor5/3\rfloor + \lfloor5/4\rfloor + \lfloor5/5\rfloor = 1 + 1 + 1 = 3 $,远小于 8;
- 若存在重复最优排列(如多个相同最小值),升序仍保证全局最优,无需额外枚举。
总结:本题本质是贪心策略应用——通过控制前缀和增长速率来最大化调和型求和。核心在于理解 floor(X / s_i) 对分母敏感性,从而得出“小数优先”的排序准则。实现时务必严格遵循题设公式,避免引入无关计算逻辑。

















