//解决一类问题即:
:::: 求和_ai/bi的最值的问题_该种题目往往存在一定的精度问题;即eps应该取多少其实这个影响这我们的时间复杂度
$\sum_{i=0}^m \frac{ai}{bi}$ 最值的问题
1. 总共会有n个物品我会从中选出m个物品使得这个分数值最大?
一般来说题目会给定一个精度eps::: |ans-k|<=eps 我们认为在这个范围内的数都是正确的
对这个式子可以进行变形:|$\sum_{i=0}^m \frac{ai}{bi}$-k|<=eps
再变:$\sum_{i=0}^m {ai-kbi}$<=eps
//或许换个思路来看也不是不可以作为最大的k
ai-k*bi的一系列求和式子都应该是小于等于那个eps或者0的
k—取到所谓的 max值我们二分边界肯定到达某个范围值 的出现就会使得条件无法满足
那样的话证明我们所给的k值过大需要使得r=mid 反之 l=mid;
这个时候是不是可以二分一下答案
sort的顺序直接影响了max还是min,why?
如果从小到大 是不是一个记录的res取到了最小的边界大于eps我们是不是需要将l=mid提升k 反之r=mid
如果从大到小–max值 取了最大的ai-kbi最大–ai/bi-k最大所以说是最大值
AC代码模板:
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <cmath>
#include <queue>
#include <sstream>
#include <cstring>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<int, PII> PIII;
typedef pair<double, double> PDD;
const int N = 1e6 + 10, M = 2 * 100010, inf = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-5;
#define x first
#define y second
#define gcd __gcd
#define sr string
#define sn scanf("%d%d",&n,&m);
#define mh memset(h,-1,sizeof h),idx=0;
#define lcm(a, b) (a/gcd(a,b))*b;
int dir[4][2] = {{-1, 0},
{0, 1},
{1, 0},
{0, -1}};
int e[M], ne[M], h[N], idx, w[M], z[M];
int n, m, p[N], k, t, res, dfn[N], low[N], tot, id[N], T;
bool st[210][210], s[210][210], flag;
int root;
unordered_map<int, int> q;
double c[N];
bool check(double x)
{
for(int i=1;i<=n;i++)
c[i]=(double)e[i]-(double)x*h[i];
sort(c+1,c+1+n);
reverse(c+1,c+1+n);
double res=0.0;
for(int i = 1; i<=m; i ++)
res += c[i];
return res>eps;
}
int main() {
sn
for(int i=1;i<=n;i++)
scanf("%d %d",&e[i],&h[i]);//数据看题
double l=0.00001,r=2e5;//这个右端点其实需要算一下,许多题数据并不完美
//设每个h[i]和e[i]的最大值x,最小值1,并且n的最大值是N---使得每个e[i]取到max (x/1)+x+....+x这样会存在N个
while (fabs(r-l)>eps)
{
double mid=(l+r)/2;
if (check(mid))
l=mid;
else
r=mid;
}
printf("%.6f\n", l);
return 0;
}