Donald is a fence builder. He wants to build a fence that is N−1N−1 meters long. He needs a fence post every meter along the fence, which means he needs NN fence posts. Donald has KK poles of varying lengths that he wants to use as fence posts. The fence posts must have the same lengths, and be as long as possible. Also, the parts of the poles that are not used for the posts must not be longer than the ones used for the posts. Donald can cut the poles as many times as he wants, and at any position he wants. However, cutting a pole takes time, so he wants to make as few cuts as possible while achieving his other goals.
How many cuts does Donald have to make to get the fence posts for his fence?
Input
The first line has two space-separated integers, KK and NN. The second line consists of KK space-separated integers p1p1, p2p2, …, pKpK, where pipi represents the length of the iith pole.
Output
Output the minimum number of cuts needed to build the fence.
Limits
1≤K≤N≤100001≤K≤N≤10000
1≤pi≤100001≤pi≤10000
Sample Input 1
1 2
3
Sample Output 1
1
Sample Input 2
2 5
4 2
Sample Output 2
4
题意:给定k根木棍,和需要分成的份数n,可以无限次切割各个木棍,使得切割而成的n份尽量长,
且长度相等,各个木棍剩余的部分不能比它长,求切割的最小次数。
分析:可知关键点在于组成这n份的木棍长度,因为最长的长度确定了,次数也随之确定,所以我们二分切割的长度,
check函数怎么写?怎么保证剩余部分小于这个长度呢?贪心处理,每根木棍能切多少切多少,如果是正好切,那么切的次数是份数-1.
二分下界是0,上界是n,指定一个精度,然后二分不断逼近这个最大值,最后再计算一遍份数就可以了。
这里浮点数计算存在误差,所以在判断浮点数相等的部分就让它们相减小于一个极小值就认为是相等
习惯性的用1e-6来判断浮点数和整数是否相等,但是这里全都用1e-6判断会WA,用1e-1到1e-5的任意的都可以,但不能用1e-6,这和题目的测试数据有关吧
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,k;
const int N=10005;
const double eps=1e-6;
int a[N];
int check(double p)///判断是否能得到n份尽可能长的木棍
{
int sum=0;
for(int i=0;i<k;i++)
{
int t=(int)(1.0*a[i]/p);
if(fabs(1.0*t*p-a[i])<=eps) t--;
sum+=t;
}
return sum>=n?1:0;///需要n份
}
int main()
{
while(~scanf("%d%d",&k,&n))
{
for(int i=0;i<k;i++)
scanf("%d",&a[i]);
double l=0,r=n,mid,MAX;
while(r-l>=eps)///二分法,一直找到最大的满足条件的MAX
{
mid=(l+r)/2.0;
if(check(mid))
{
MAX=mid;
l=mid;
}
else r=mid;
}
int ans=0;
for(int i=0;i<k;i++)
{
int t=(int)(1.0*a[i]/MAX);//MAX为满足题目条件的最大长度
if(fabs(1.0*t*MAX-a[i])<=1e-1) ///这里的精度判断不能比1e-5小,可以是1e-1到1e-5
t--;
ans+=t;
}
printf("%d\n",ans);
}
return 0;
}