Description
儿童节那天有 KK 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
小明一共有 NN 块巧克力,其中第 ii 块是 Hi×WiHi×Wi 的方格组成的长方形。
为了公平起见,小明需要从这 NN 块巧克力中切出 KK 块巧克力分给小朋友们。切出的巧克力需要满足:
-
形状是正方形,边长是整数。
-
大小相同。
例如一块 6×56×5 的巧克力可以切出 66 块 2×22×2 的巧克力或者 22 块 3×33×3 的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小 HiHi 计算出最大的边长是多少么?
Input
第一行包含两个整数 NN 和 KK。(1≤N,K≤105)(1≤N,K≤105)。
以下 NN 行每行包含两个整数 HiHi 和 WiWi。(1≤Hi,Wi≤105)(1≤Hi,Wi≤105)。
输入保证每位小朋友至少能获得一块 1×11×1 的巧克力。
Output
输出切出的正方形巧克力最大可能的边长。
Sample 1
Inputcopy | Outputcopy |
---|---|
2 10 6 5 5 6 | 2 |
Hint
蓝桥杯 2022 省赛 A 组 I 题。
解决方案
变量和输入
int heights[100000], widths[100000];
int numRectangles, requiredSquares;
heights[100000]
和widths[100000]
:分别存储每个矩形的高度和宽度。numRectangles
:矩形的数量。requiredSquares
:需要切割出的正方形数量。
函数 canCutSquares(int sideLength)
这个函数用于检查是否可以用边长为 sideLength
的正方形切割出至少 requiredSquares
个正方形。
bool canCutSquares(int sideLength) {
int count = 0;
for (int i = 0; i < numRectangles; i++) {
count += (heights[i] / sideLength) * (widths[i] / sideLength);
}
return count >= requiredSquares;
}
count
:计数器,记录可以切割出的正方形数量。- 对于每一个矩形,计算其高度和宽度分别能被
sideLength
整除的次数,然后相乘得到该矩形内可以切割出的正方形数量,并累加到count
中。 - 如果
count
大于或等于requiredSquares
,返回true
(表示可以切割出足够多的正方形);否则返回false
。
主函数 main()
主函数负责读取输入数据,并通过二分查找找到最大的满足条件的 sideLength
。
int main() {
cin >> numRectangles >> requiredSquares;
int maxSideLength = 0;
for (int i = 0; i < numRectangles; i++) {
cin >> heights[i] >> widths[i];
maxSideLength = max(maxSideLength, max(heights[i], widths[i]));
}
int left = 1, right = maxSideLength;
while (left < right) {
int mid = (left + right + 1) / 2;
if (canCutSquares(mid)) {
left = mid;
} else {
right = mid - 1;
}
}
cout << left;
return 0;
}
- 首先读取
numRectangles
和requiredSquares
。 - 然后读取每个矩形的高度和宽度,并找出所有矩形中的最大值
maxSideLength
。 - 初始化二分查找的范围
left
和right
,分别为1
和maxSideLength
。 - 使用二分查找不断调整范围,直到找到最大的满足条件的
sideLength
。 - 最后输出结果
left
,即最大的满足条件的sideLength
。
总结
通过二分查找的方法高效地解决了寻找最大边长的问题,使得在给定的矩形中可以切割出至少 k
个边长为 d
的小正方形。完整代码如下:
#include <iostream>
using namespace std;
int heights[100000], widths[100000];
int numRectangles, requiredSquares;
bool canCutSquares(int sideLength) {
int count = 0;
for (int i = 0; i < numRectangles; i++) {
count += (heights[i] / sideLength) * (widths[i] / sideLength);
}
return count >= requiredSquares;
}
int main() {
cin >> numRectangles >> requiredSquares;
int maxSideLength = 0;
for (int i = 0; i < numRectangles; i++) {
cin >> heights[i] >> widths[i];
maxSideLength = max(maxSideLength, max(heights[i], widths[i]));
}
int left = 1, right = maxSideLength;
while (left < right) {
int mid = (left + right + 1) / 2;
if (canCutSquares(mid)) {
left = mid;
} else {
right = mid - 1;
}
}
cout << left;
return 0;
}