【洛谷题解】分巧克力 二分

题目地址:分巧克力https://www.luogu.com.cn/problem/P8647

题目描述

儿童节那天有 K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。

小明一共有 N块巧克力,其中第 i块是 Hi​×Wi​ 的方格组成的长方形。

为了公平起见,小明需要从这 NN 块巧克力中切出 KK 块巧克力分给小朋友们。切出的巧克力需要满足:

  1. 形状是正方形,边长是整数。

  2. 大小相同。

例如一块6×5 的巧克力可以切出 6 块 2×2 的巧克力或者 2块 3×3 的巧克力。

当然小朋友们都希望得到的巧克力尽可能大,你能帮小 明 计算出最大的边长是多少么?

输入格式

第一行包含两个整数 N 和 K。(1≤N,K≤105)。

以下 N 行每行包含两个整数 Hi​ 和 Wi​。(1≤Hi​,Wi​≤105)。

输入保证每位小朋友至少能获得一块 1×1 的巧克力。

输出格式

输出切出的正方形巧克力最大可能的边长。

输入输出样例

输入 #1复制

2 10  
6 5  
5 6  

输出 #1复制

2

二分模板:

mid=(l+r)/2

if(check(mid)){

    true  [1,mid] r=mid;

    false  [mid+1,r]  l=mid+1;

}

此题:

res记作巧克力的总块数,x记作每块巧克力的边长,用二分的思想,mid记作边长,当边长为mid时,res大于k,即符合要求时,更新l=mid+1,使mid边长加大,每个小朋友分到的巧克力更大,如果res小于k,即巧克力数小于小朋友数,更新r=mid-1,使mid边长减小

 

思考:此题是求最大边长,但是是以最小块数为切口,最小值,所以用第一个模板 

第一种写法 

#include
using namespace std;
const int N=1e5+5;
int n,k;
int a[N],b[N];

int check(int x){  //x为边长 
	int ans=0;   //ans为巧克力块数 
	for(int i=1;i<=n;i++){
		ans+=(a[i]/x)*(b[i]/x);
	}
	return ans;
}

int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
	}
	
	int l=1,r=1e6;
	while(lk,整数,减一即可满足 
	return 0;
}

	//另一种类型 
	/* 
	while(l  < r){
		int mid = l + r + 1 >> 1;
		if(check(mid) >= k){
			l = mid;
		}
		else r = mid - 1;
	}cout << l;
	*/
	

第二种写法 

#include
using namespace std;
const int N=1e5+5;
int n,k;
int a[N],b[N];
 
int check(int x){  //x为边长 
	int ans=0;   //ans为巧克力块数 
	for(int i=1;i<=n;i++){
		ans+=(a[i]/x)*(b[i]/x);
	}
	return ans;
}
 
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
	}
	
	int l=1,r=1e6;
	while(l<=r){
		int mid=(l+r)/2;
		if(check(mid)k,整数,减一即可满足 
	return 0;
}

你可能感兴趣的:(题解,数据结构)