-
题目:
儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有N块巧克力,其 中第i块是Hi x Wi的方格组成的长方形。为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们.切出的巧克力需要满足:
1. 形状是正方形,边长是整数
2. 大小相同
例如一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。当然小朋友们都希望得到的巧克力尽可能大,你能帮小Hi计算出最大的边长是多少么?
-
输入和输出
输入:
第一行输入包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000)
输入保证每位小朋友至少能获得一块1x1的巧克力。
输出:
输出切出的正方形巧克力最大可能的边长。
样例输
2 10
6 5
5 6
样例输出:
2
-
分析过程
首先对于一块巧克力切割成边长为a的巧克力时所切割的最大数量为 n=[h/a]*[w/a]
因此得构造计算出小明切割边长为a的巧克力所用的数量是否大于等于小朋友数量的函数
#include<stdio.h> int a,b; //a,b分别为小明巧克力数量和小朋友数量 int h[100001],w[100001]; //h,w分别为每一个巧克力的长和宽 int fun(int k) //k为切出边长为k的巧克力 { int sum=0; //num为所的边长为k的切巧克力的数量 for(int i=0;i<a;i++) //a为小明的巧克力总数 { sum+=(h[i]/k)*(w[i]/k); //这里num放在for里面只要满足条件就中止循环,能减少循环次数 if(sum>=b) return 1; } return 0; }
接下来是查找k的值的分析,由于k介于1的100000之间且k是顺序存储结构并且连续增大,故推荐二分查找法
当然这里的100000进入fun函数时sum相加一直为零,当r=l时此时的r和l指的是刚好可以分得的巧克力的数量但还会进入循环,循环后l会加一,故得输出r
int l=0,r=100000,mid; while(l<=r) { mid=(l+r)/2; if(fun(mid)) l=mid+1; else r=mid-1; }
接下来是整体代码
#include<stdio.h> int a,b; //a,b分别为小明巧克力数量和小朋友数量 int h[100001],w[100001]; //h,w分别为每一个巧克力的长和宽 int fun(int k) //k为切出边长为k的巧克力 { int sum=0; //num为所的边长为k的切巧克力的数量 for(int i=0;i<a;i++) //a为小明的巧克力总数 { sum+=(h[i]/k)*(w[i]/k); //这里num放在for里面只要满足条件就中止循环,能减少循环次数 if(sum>=b) return 1; } return 0; } int main() { int l=1,r=100000,mid; scanf("%d%d",&a,&b); for(int i=0;i<a;i++) scanf("%d%d",&h[i],&w[i]); while(l<=r) { mid=(l+r)/2; if(fun(mid)) l=mid+1; else r=mid-1; } printf("%d",r); return 0; }