原题
问题描述
儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
小明一共有 N 块巧克力,其中第 i 块是Hi×Wi 的方格组成的长方形。为了公平起见,
小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:
-
形状是正方形,边长是整数;
-
大小相同;
例如一块 6×5 的巧克力可以切出 6 块 2×2 的巧克力或者 2 块 3×3 的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?
输入描述
第一行包含两个整数 N,K (1≤N,K≤10^5)。
以下 N 行每行包含两个整数Hi,Wi (1≤Hi,Wi≤10^5)。
输入保证每位小朋友至少能获得一块 1x1 的巧克力。
输出描述
输出切出的正方形巧克力最大可能的边长。
输入输出样例
示例
输入
2 10
6 5
5 6
输出
2
运行限制
- 最大运行时间:2s
- 最大运行内存: 256M
解题思路
首先确定范围1<=ans<=Max,Max我没找了,直接举一个超过数据范围的数。然后用二分收缩,这样只需要log2(n)次。
每一次我们都要确定这个数是大了还是小了,这个我没办法,只能一个个的去比较,时间复杂度为O(n)。
怎么确定他能分几块?
直接x=h/mid,y=w/mid,得到的就是这块巧克力最大分几块了,用一个cnt去统计所有总数,这样每次的结果就出来了,满足的话,那么l=mid+1,记录Mid,不满足就r=mid。
这里需要注意的是,巧克力可以浪费一整块。
总时间复杂度O(nlog2(m))
题解
#include <iostream>
#include <algorithm>
using namespace std;
const int N=10e5+5;
struct Chocolate{
int h;
int w;
}chocolate[N];
int n,k,Max;
bool judge(int mid){
int cnt=0;
for(int i=1;i<=n;i++){
//if(mid>chocolate[i].h||mid>chocolate[i].w) return false; 可以直接舍弃这一块
int x,y;
x=chocolate[i].h/mid;
y=chocolate[i].w/mid;
cnt+=x*y;
}
return cnt>=k;
}
void lower_bound(int l,int r){
while(l<r){
int mid=(l+r)>>1;
if(judge(mid)){
l=mid+1;
Max=mid;
}
else r=mid;
}
}
int main()
{
// 请在此输入您的代码
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>chocolate[i].h>>chocolate[i].w;
}
lower_bound(1,N);
cout<<Max;
return 0;
}