[五校联考4]淬炼神体

题目大意

给定n组数,选取k组数,每组数都有一个A值和B值,ans=(∑a)/(∑b)

求ans值最大,保留3为小数

题目解析

最简单的方法就是dfs枚举,求出所有ans值,取最大

正解:

一、先拆分公式
ans=(∑a)/(∑b)
(∑a)=ans*(∑b)
(∑a)-(∑b)*ans=0 (此时的ans值最大)
经过化简可得:

∑ai-bi*ans=0

所以利用二分枚举ans

二、二分:
1、枚举ans后计算出∑ai-bi*ans,按升序排序后,取前k个

2、二分的条件
因为(∑a)-(∑b)*ans=0 时ans值最大
所以
当(∑a)-(∑b)*ans>=0时,增大ans来减小∑ai-bi*ans
当(∑a)-(∑b)*ans<0时,减小ans来增大∑ai-bi*ans

因为(∑a)-(∑b)*ans可能在c++中的精度中无法达到0,所以当r-l>10-5,就跳出循环

代码

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,k;
double a[N],b[N],c[N],s,ans;
bool cmp(double a,double b)
{
	return a>b;
}
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	 cin>>a[i];
    for(int i=1;i<=n;i++)
     cin>>b[i];
    double l=0.001,r=1000,mid;
    while(r-l>1e-5)//二分 
    {
   	  mid=(l+r)/2.0;
   	  for(int i=1;i<=n;i++)
   	   c[i]=a[i]-b[i]*mid;//求出∑ai-bi*ans
      sort(c+1,c+1+n,cmp);
      s=0;
      for(int i=1;i<=k;i++)
       s+=c[i];
      if(s>0)
      {
      	l=mid;
      	ans=max(ans,mid);
      }
      if(s<0) r=mid;
    }
    cout<<fixed<<setprecision(3)<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值