1 条题解
-
0
这道题的核心是通过建立切割次数与矩形数量的数学关系,结合边界约束,求解水平切割次数和垂直切割次数。关键在于先推导公式,再枚举可能的值验证合法性,最终找到最优解。
一、核心公式与约束条件
首先明确两个核心关系,这是解题的基础:
- 矩形数量公式:水平切割次会将矩形分成行,垂直切割次会分成列,因此总矩形数为 。
- 总切割次数公式:总切割次数为水平与垂直切割次数之和,即 。
同时需满足以下边界约束(切割次数不能超过最大可能值):
- 水平切割上限:(矩形高度为,最多有条水平切割线)。
- 垂直切割上限:(矩形宽度为,最多有条垂直切割线)。
- 非负约束:,。
二、解题步骤
基于上述公式,可通过“枚举的可能值→计算→验证所有约束”的流程求解,具体步骤如下:
- 公式变形:由得,代入矩形数量公式得 。我们需要找到满足该等式且符合所有约束的。
- 确定的枚举范围:
- 由得。
- 由和得的下限为,上限为。
- 此外,必须是的约数(否则不是整数,无法满足矩形数量公式),因此只需枚举的所有约数,令,再验证是否在上述范围内。
- 验证约束:对每个枚举的,计算,检查:
- (确保矩形数量正确)。
- 且(垂直切割次数合法)。
- 选择最优解:若存在多个合法的,选择最小的(题目要求“水平切割次数最少”);若无合法解,输出。
三、关键优化:枚举的约数
由于可能极大(最大),直接枚举的所有可能值会超时,因此需通过“枚举的约数”减少计算量:
- 约数的性质:若是的约数,则也是的约数,因此只需枚举到即可,时间复杂度为,对于而言,最大为,但结合的范围限制(),实际枚举量会大幅减少。
四、实现代码
#include <bits/stdc++.h> using namespace std; using ll = long long; void solve() { ll a, b, k, m; cin >> a >> b >> k >> m; vector<pair<ll, ll>> candidates; // 存储合法的(h, v)对 // 枚举m的所有约数d,d = h+1 => h = d-1 ll max_div = sqrt(m); for (ll d = 1; d <= max_div; ++d) { if (m % d != 0) continue; // 情况1:d = h+1,v+1 = m/d ll h = d - 1; ll v_plus_1 = m / d; ll v = v_plus_1 - 1; // 验证约束条件 if (h >= 0 && h <= a - 1 && h <= k && // h的合法性 v >= 0 && v <= b - 1 && v == k - h) { // v的合法性 candidates.emplace_back(h, v); } // 情况2:m/d = h+1,v+1 = d(避免d与m/d相等时重复添加) if (d != m / d) { ll h2 = (m / d) - 1; ll v2_plus_1 = d; ll v2 = v2_plus_1 - 1; if (h2 >= 0 && h2 <= a - 1 && h2 <= k && v2 >= 0 && v2 <= b - 1 && v2 == k - h2) { candidates.emplace_back(h2, v2); } } } if (candidates.empty()) { cout << -1 << "\n"; } else { // 按h升序排序,取最小h的解 sort(candidates.begin(), candidates.end()); cout << candidates[0].first << " " << candidates[0].second << "\n"; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
五、代码解释与复杂度分析
- 约数枚举:通过
math.isqrt(m)
获取,枚举到的所有整数,判断是否为的约数,同时处理和两种约数情况,避免遗漏。 - 约束验证:对每个约数对应的,计算后逐一验证边界约束,确保切割次数合法。
- 最优解选择:将所有合法的对按升序排序,取第一个即为“水平切割次数最少”的解。
复杂度分析
- 时间复杂度:每组测试数据的时间主要用于枚举的约数,为。由于且(但实际因,枚举量会更小),可满足时间要求。
- 空间复杂度:(仅存储少量候选解,可忽略)。
六、算法标签
- 数学推导
- 枚举与验证
- 约束条件分析
七、样例验证
以第三组样例()为例:
- 枚举的约数:。
- 对每个约数计算:
- :,→。验证:(合法),(合法),(合法),因此是合法解。
- 无其他合法解,输出,与样例一致。
- 1
信息
- ID
- 3211
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者