题目背景
要保护环境
题目描述
木材厂有 n 根原木,现在想把这些木头切割成 k 段长度均为l的小段木头(木头有可能有剩余)。
当然,我们希望得到的小段木头越长越好,请求出 l 的最大值。
木头长度的单位是cm,原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数。
例如有两根原木长度分别为 11 和 21,要求切割成等长的 6 段,很明显能切割出来的小段木头长度最长为 5。
输入格式
第一行是两个正整数 n,k,分别表示原木的数量,需要得到的小段的数量。
接下来 n 行,每行一个正整数Li,表示一根原木的长度。
输出格式
仅一行,即 l 的最大值。
如果连1cm 长的小段都切不出来,输出 0
。
输入输样例
输入 #1
3 7 232 124 456
输出 #1
114
1<=n<=100000 1<=k<=100000000 1<=Li<=100000000
分析
需要注意使用long long或unsigned long来定义(测试点里有几个很大的数据,用int可能会爆)
二分:
取中点,然后判断 分出的段数 与 输入小段的数量k 的大小。
如果大于等于就在左边,否则右边
bool aa(unsigned long mid)
{
unsigned long sum=0;
for(int i=0; i<n; i++)
sum+=a[i]/mid;
return sum>=k;
}
在选择区间时最好选择最大的那个,否则要分好几种情况,有点麻烦。
代码
#include <iostream>
#include<algorithm>
#define q 100005
using namespace std;
typedef unsigned long ll; //类型定义
unsigned int a[q],n;
ll k;
bool cmp(int a,int b)
{
return a>b; //使sort从大到小排列
}
bool aa(ll mid)
{
ll sum=0;
for(int i=0; i<n; i++) //判断
sum+=a[i]/mid;
return sum>=k;
}
int main()
{
cin>>n>>k;
for(int i=0; i<n; i++)
cin>>a[i];
sort(a,a+n,cmp); //最简单是用max()来求其中最大木头长度
int left=0;
ll right=a[0];
unsigned int mid=a[0]/2;
while(left+1<right)
{
mid=(left+right)/2;
if(aa(mid))left=mid; //二分
else right=mid;
}
cout<<left;
}