题目大意
给定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;
}