1 条题解
-
0
D. Place of the Olympiad 详细题解
一、问题重述
有一个 的矩形场地,要放置 个桌位。桌位只能放在格子里,同一行中连续放置的桌位形成一条长凳。要求最小化最长长凳的长度。
例如, 时,最优安排是每行最多连续 个桌位,答案为 。
二、核心思路
2.1 函数定义
设最长长凳长度为 。在一行中,如何安排才能容纳最多的桌位?
- 将每 个位置视为一个块:前 个位置放桌位(形成一个长凳),第 个位置空出作为分隔。
- 每行可以放 个完整的块,产生 个桌位。
- 最后剩余 个位置,可以再放 个桌位(若余数小于等于 则全放,否则不能超过 ,但余数肯定小于 ,所以当余数为 时也可以放 个)。
因此一行最多容纳的桌位数为:
$$f(x) = x \cdot \left\lfloor \frac{m}{x+1} \right\rfloor + \min\left(m \bmod (x+1),\; x\right) $$实际余数部分就是 ,因为余数 ,且当余数等于 时也可以放 个。所以:
$$f(x) = x \cdot \left\lfloor \frac{m}{x+1} \right\rfloor + \left(m \bmod (x+1)\right) $$2.2 可行性条件
由于 行独立,总共最多可以放 个桌位。要能容纳 个桌位,需满足:
2.3 单调性
当 增大时, 也单调非减(允许更长的长凳,可以放更多桌位)。因此可以用二分查找最小的 满足 。
三、公式推导(可选)
对于给定 ,$f(x) = \left\lceil \frac{m}{x+1} \cdot x \right\rceil$ 的近似?不精确。更简单的:一行中最少需要的空位数为 个桌位时,用二分找 。
但标程使用二分查找,简洁有效。
四、标程代码
#include <iostream> using namespace std; void solve() { long long n, m, k; cin >> n >> m >> k; long long l = 0, r = m; // 答案在 [1, m] 之间 while (l + 1 < r) { long long mid = (l + r) / 2; // 计算当最大 bench 长度为 mid 时,一行最多能放多少个座位 long long seats_per_row = (m / (mid + 1)) * mid + (m % (mid + 1)); if (seats_per_row * n >= k) { r = mid; // 可行,尝试更小的长度 } else { l = mid; } } cout << r << endl; } int main() { int t; cin >> t; while (t--) { solve(); } return 0; }
五、示例验证
示例 1:
- 二分:
- :每块长度 (), 块 → ,余数 → 可加 ,共 个/行, ✅ →
- :每块长度 , 块 → ,余数 ,共 个/行, ❌ → 最终 ✅
示例 2:
- :每块长度 , 块 → ,余数 → 共 个/行, ✅ → 继续缩小
- :每块长度 , 块 → ,余数 ,共 个/行 ❌ → 答案为 ✅
示例 3:
- 最长 bench 长度为 时,一行最多放 $\lfloor 13/2 \rfloor \times 1 + (13\%2)=6+1=7 \ge 2$ ✅ → 答案为 ✅
六、复杂度分析
- 二分查找:
- 总复杂度:,,,完全可行
七、总结
步骤 操作 1 二分答案 (最长 bench 长度) 2 计算当 bench 长度为 时,一行最多能放的座位数 3 若 ,则 可行,缩小右边界 4 否则增大左边界 核心公式:
$$f(x) = x \cdot \left\lfloor \frac{m}{x+1} \right\rfloor + \left(m \bmod (x+1)\right) $$利用二分查找最小 满足 。
- 1
信息
- ID
- 7263
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者