P1577 切绳子

题目https://www.luogu.com.cn/problem/P1577?contestId=224842https://www.luogu.com.cn/problem/P1577?contestId=224842https://www.luogu.com.cn/problem/P1577?contestId=224842https://www.luogu.com.cn/problem/P1577?contestId=224842https://www.luogu.com.cn/problem/P1577?contestId=224842

题目描述

我们有 n 条绳子,每条绳子长度为a1, a2, a3 ...an 。我们要将这些绳子切成一模一样的 k 段,要保证每段长度 m(保留两位小数,计算时不考虑四舍五入)最大,输出 m 。

题目思路

  • 二分法。1.可行性:当 k 值越大时,m 的值呈单调递减。2.必要性:如果采用暴力拆解法,时间复杂度 O(n*n+n),但用二分法时间复杂度就只有 O(log2(n)*n+n)。在 n 较大时有奇效。(成也暴力拆解法,败也暴力拆解法,会 TLE【Time Limit Exceeded】的痛)

  • 因为每一个数都是保留小数点后两位,而且不考虑四舍五入,这明摆着出题人想要我们将这些数据改成整数进行运算。即,将每一个数乘 100,进行整数的二分法运算,在最后除以 100 后输出。

  • 注意 small 要小于最小的情况,big 要大于最大的情况。

  • 有可能我们将绳子切成 0.01 的长度 m 还是小于 k,这种情况我们无论怎么切绳子都达不到 k 条。即,将每一个元素累加的和 sum 与 k 比较,比 k 小的输出 0.00,并结束程序。

  • 尽管 k 不会超出 int,但是我们的 sum 可能会超出 int,需要将 sum 的数据类型定义为 long long

代码实现

#include<iostream>
using namespace std;
int main(){
	int n,k,m=0;cin>>n>>k;int a[n],small=-1,big=0;long long sum=0;
	for(int i=0;i<n;i++){
		double temp;cin>>temp;a[i]=temp*100;
		if(big<a[i])big=a[i];
		sum+=a[i];
	}
	big++;
	if(k>sum){cout<<"0.00"<<endl;return 0;}
	while(small<big){
		int mid=(small+big)/2;m=0;
		for(int i=0;i<n;i++)m+=(a[i]/mid);
		if(m>=k)small=mid+1;
		else big=mid;
	}
	cout<<(big-1.0)/100<<endl;
	return 0;
}

输入输出 

 样例输入1:

4 11
8.02
7.43
4.57
5.39

输出:

2.00

输入样例2:

1 10000
1.00

输出:

0.00

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值