题干:

In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be

.

Given your test scores and a positive integer k, determine how high you can make your cumulative average if you are allowed to drop any k of your test scores.

Suppose you take 3 tests with scores of 5/5, 0/1, and 2/6. Without dropping any tests, your cumulative average is . However, if you drop the third test, your cumulative average becomes .

题目大意:

给出n个物品,每个物品有两个属性a和b,选择n-k个元素,询问的最大值。

1<=n<=1000,0<=k<n,0<=ai<=bi<=1000000000。

解题报告:

   典型的分数规划。

  首先答案是符合单调性的,而就等价于

所以我们发现二分完把ai-x*bi排序后把最大的n-k个选出来就行了。

AC代码:(80ms)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
int n,k;
const double eps = 1e-5;
double qq[MAX];
struct Node {
	double a,b;
} node[MAX];
bool ok(double x) {
	double res = 0;
	for(int i = 1; i<=n; i++) qq[i] = node[i].a - x * node[i].b;
	sort(qq+1,qq+n+1); 
	for(int i = n; i>=k+1; i--) res += qq[i];
	return res >= 0;
}
int main()
{
	while(~scanf("%d%d",&n,&k) && n+k) {
		for(int i = 1; i<=n; i++) scanf("%lf",&node[i].a);
		for(int i = 1; i<=n; i++) scanf("%lf",&node[i].b);
		double l = 0,r = 1e9;
		double mid = (l+r)/2;
		while(l+eps < r) {
			mid = (l+r)/2;
			if(ok(mid)) l = mid;
			else r = mid;
		}
		printf("%d\n",(int)(round(l*100)));//mid-eps?
	}


	return 0 ;
 }

迭代法可以快很多:(30ms)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
int n,k;
const double eps = 1e-5;
double qq[MAX],aa,bb;
struct Node {
	double a,b;
} node[MAX];
struct NN {
	double a,b,qq;
} q[MAX];
bool cmp(NN a,NN b) {
	return a.qq < b.qq;
}
double ok(double x) {
	double res = 0;
	aa=bb=0;
	for(int i = 1; i<=n; i++) q[i].qq = node[i].a - x * node[i].b,q[i].a = node[i].a,q[i].b = node[i].b;
	sort(q+1,q+n+1,cmp); 
	for(int i = n; i>=k+1; i--) aa += q[i].a,bb += q[i].b;
	return aa/bb;
}
int main()
{
	while(~scanf("%d%d",&n,&k) && n+k) {
		for(int i = 1; i<=n; i++) scanf("%lf",&node[i].a);
		for(int i = 1; i<=n; i++) scanf("%lf",&node[i].b);
		double l = 0,r = 1e9;
		double mid = (l+r)/2,ans = -1;
		while(fabs(ans-mid) >= eps) {
			ans = mid;
			mid = ok(mid);
		}
		printf("%d\n",(int)(round(ans*100)));//mid-eps?
	}


	return 0 ;
 }