234. 放弃测试

题目链接

234. 放弃测试

在某个课程中,你需要进行 \(n\) 次测试。

如果你在共计 \(b_i\) 道题的测试 \(i\) 上的答对题目数量为 \(a_i\),你的累积平均成绩就被定义为

image

给定您的考试成绩和一个正整数 \(k\),如果您被允许放弃任何 \(k\) 门考试成绩,您的累积平均成绩的可能最大值是多少。

假设您进行了 \(3\) 次测试,成绩分别为 \(5/5,0/1\)\(2/6\)

在不放弃任何测试成绩的情况下,您的累积平均成绩是image

然而,如果你放弃第三门成绩,则您的累积平均成绩就变成了image

输入格式

输入包含多组测试用例,每个测试用例包含三行。

对于每组测试用例,第一行包含两个整数 \(n\)\(k\)

第二行包含 \(n\) 个整数,表示所有的 \(a_i\)

第三行包含 \(n\) 个整数,表示所有的 \(b_i\)

当输入用例 \(n=k=0\) 时,表示输入终止,且该用例无需处理。

输出格式

对于每个测试用例,输出一行结果,表示在放弃 \(k\) 门成绩的情况下,可能的累积平均成绩最大值。

结果应四舍五入到最接近的整数。

数据范围

\(1≤n≤1000,\)
\(0≤k<n,\)
\(0≤a_i≤b_i≤10^9\)

输入样例:

3 1
5 0 2
5 1 6
4 2
1 2 7 9
5 6 7 9
0 0

输出样例:

83
100

解题思路

01分数规划:给定整数 \(a_{1}, a_{2}, \cdots, a_{n}\) 以及 \(b_{1}, b_{2}, \cdots, b_{n}\), 求一组解 \(x_{i}\left(1 \leq i \leq n, x_{i}=0\right. or 1)\), 使下式最大化:

\[\frac{\sum_{i=1}^{n} a_{i} * x_{i}}{\sum_{i=1}^{n} b_{i} * x_{i}} \]

解法(二分):
假设 \(L=\frac{\sum_{i=1}^{n} a_{i} * x_{i}}{\sum_{i=1}^{n} b_{i} * x_{i}}\),存在一组解,使得 \(\sum_{i=1}^{n}\left(a_{i}-L * b_{i}\right) * x_{i} \geq 0\),即:\(\exists\left\{x_{1}, x_{2}, \cdots, x_{n}\right\}\), 使得 \(\frac{\sum_{i=1}^{n} a_{i} * x_{i}}{\sum_{i=1}^{n} b_{i} * x_{i}} \geq L\),即存在更大的值比当前值要大,\(L\) 过小;否则,如果任意的解都有 \(\sum_{i=1}^{n}\left(a_{i}-L * b_{i}\right) * x_{i} < 0\),即:\(\frac{\sum_{i=1}^{n} a_{i} * x_{i}}{\sum_{i=1}^{n} b_{i} * x_{i}} < L\),即 \(L\) 比任意解都要大,\(L\) 过大,判断点在于最大值是否非负,因此具有二段性,可用二分找出最大

本题要求最多抛弃 \(k\) 门考试成绩,判断时可直接丢掉最小的 \(k\) 个值在进行判断即可

\(m\) 为不确定数,与精度有关,则:

  • 时间复杂度:\(O(nlogm)\)

代码

// Problem: 放弃测试
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/236/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const double eps=1e-6;
const int N=1005;
int n,k;
double a[N],b[N],c[N];
bool ck(double x)
{
	for(int i=1;i<=n;i++)c[i]=a[i]-x*b[i];
	sort(c+1,c+1+n);
	double res=0;
	for(int i=k+1;i<=n;i++)res+=c[i];
	return res>=0;
}
int main()
{
    while(cin>>n>>k,n!=0||k!=0)
    {
    	
    	for(int i=1;i<=n;i++)cin>>a[i];
    	for(int i=1;i<=n;i++)cin>>b[i];
    	double l=0,r=1;
    	while(r-l>eps)
    	{
    		double mid=(l+r)/2;
    		if(ck(mid))l=mid;
    		else
    			r=mid;
    	}
    	cout<<int(l*100+0.5)<<'\n';
    }
    return 0;
}
posted @ 2022-03-03 16:44  zyy2001  阅读(73)  评论(0编辑  收藏  举报