二分-蓝桥杯省赛-分巧克力
题目:
儿童节那天有 K 位小朋友到小明家做客。
小明拿出了珍藏的巧克力招待小朋友们。
小明一共有 N 块巧克力,其中第 i 块是 Hi×Wi 的方格组成的长方形。
为了公平起见,小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。
切出的巧克力需要满足:
形状是正方形,边长是整数
大小相同
例如一块 6×5 的巧克力可以切出 6 块 2×2 的巧克力或者 2 块 3×3 的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?
输入格式
第一行包含两个整数 N 和 K。
以下 N 行每行包含两个整数 Hi 和 Wi。
输入保证每位小朋友至少能获得一块 1×1 的巧克力。
输出格式
输出切出的正方形巧克力最大可能的边长。
数据范围
1≤N,K≤105,
1≤Hi,Wi≤105
输入样例:
2 10
6 5
5 6
输出样例:
2
题意:
N
个
矩
形
,
现
将
N
个
矩
形
等
分
成
K
个
正
方
形
,
求
正
方
形
的
最
大
边
长
。
数
据
保
证
满
足
至
少
可
分
成
K
个
1
×
1
的
正
方
形
。
N个矩形,现将N个矩形等分成K个正方形,求正方形的最大边长。\\数据保证满足至少可分成K个1×1的正方形。
N个矩形,现将N个矩形等分成K个正方形,求正方形的最大边长。数据保证满足至少可分成K个1×1的正方形。
题解:
答
案
满
足
二
段
性
,
考
虑
二
分
法
。
答案满足二段性,考虑二分法。
答案满足二段性,考虑二分法。
二 分 正 方 形 边 长 为 m , 对 第 i 块 H i × W i 的 矩 形 而 言 , 最 多 可 以 分 成 ⌊ H i m ⌋ ⋅ ⌊ W i m ⌋ 块 . 二分正方形边长为m,对第i块H_i×W_i的矩形而言,最多可以分成\lfloor\frac{H_i}{m}\rfloor·\lfloor\frac{W_i}{m}\rfloor块. 二分正方形边长为m,对第i块Hi×Wi的矩形而言,最多可以分成⌊mHi⌋⋅⌊mWi⌋块.
所 以 对 每 个 矩 形 能 够 分 得 的 正 方 形 数 量 求 和 s u m = ∑ i = 1 N ⌊ H i m ⌋ ⋅ ⌊ W i m ⌋ , 求 得 使 得 s u m > = K 的 最 大 边 长 。 所以对每个矩形能够分得的正方形数量求和\\sum=\sum_{i=1}^N \lfloor\frac{H_i}{m}\rfloor·\lfloor\frac{W_i}{m}\rfloor ,求得使得sum>=K的最大边长。 所以对每个矩形能够分得的正方形数量求和sum=∑i=1N⌊mHi⌋⋅⌊mWi⌋,求得使得sum>=K的最大边长。
注意:
二 分 的 时 候 注 意 , 若 当 前 二 分 的 边 长 能 够 分 得 的 巧 克 力 数 量 s u m 是 大 于 等 于 人 数 K 的 , 则 代 表 方 案 可 行 , 二分的时候注意,若当前二分的边长能够分得的巧克力数量sum是大于等于人数K的,则代表方案可行, 二分的时候注意,若当前二分的边长能够分得的巧克力数量sum是大于等于人数K的,则代表方案可行,
也 就 是 说 s u m ≥ K 时 可 行 , 分 作 一 类 , 此 时 更 新 l = m i d , 否 则 更 新 r = m i d − 1 。 也就是说 sum\ge K时可行,分作一类,此时更新l=mid,否则更新r=mid-1。 也就是说sum≥K时可行,分作一类,此时更新l=mid,否则更新r=mid−1。
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=1e5+10;
int n,k;
int H[N],W[N];
int cal(int x)
{
int res=0;
for(int i=1;i<=n;i++) res+=(W[i]/x)*(H[i]/x);
return res;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d%d",&H[i],&W[i]);
int l=1, r=1e5;
while(l<r)
{
int mid=l+r+1>>1;
if(cal(mid)<k) r=mid-1;
else l=mid;
}
printf("%d\n",l);
return 0;
}