分巧克力


分巧克力


儿童节那天有 K 位小朋友到小明家做客。

小明拿出了珍藏的巧克力招待小朋友们。

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

为了公平起见,小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。

切出的巧克力需要满足:

  1. 形状是正方形,边长是整数
  2. 大小相同

例如一块 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

本题可以简化成

在1-1e5之中,找一个最大的mid,使得check(mid) 的值>=target,最后返回这样一个最大的值即可。

由于上升序列,我们可以用二分来进行查找。(属于二分的妙用了)。

说真的,到现在我还是不怎么会真正的将二分给活用,唉,用的比较机械,对边界条件还是需要花时间来进行考虑,还是要多加练习吧。

#include 

using namespace std ;

const int N = 1e5 + 5 ; 

int n , m ;

int a[N] , b[N] ; 

int check(int num)
{
    int res = 0  ;
    for(int i = 1 ; i <= n ; ++ i)
    {
        int ans = (a[i]/num)*(b[i]/num) ; 
        res += ans ; 
    }
    return res ; 
}

int main()
{
    cin >> n >> m ;
    
    for(int i = 1 ; i <= n ; ++ i)
    {
        cin >> a[i] >> b[i] ; 
    }
    
    int l  = 1 ; int r = 100000 ; 
    while(l < r)
    {
        int mid = l + r + 1 >> 1 ; 
        if(check(mid) >= m)
        {
            l = mid ; 
        }
        else
        {
            r = mid -1  ;
        }
    }
    cout << l << endl ; 
    
    return  0 ; 
}

主要的经验是,一是可以对题目进行深度提炼。

二是,查找的时候,二分可以查找符合条件的第一个与最后一个,像本题就是查找最后一个。翻译成中文就是从1到100000里面找一个数,这个数要符合check的条件,同时这个数要是这个集合中最大的,对于上升序列来说,其实就是查找符合条件的最右边的数字。


文章作者: 罗林
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗林 !
  目录