Límite de tiempo: 1000 MS | Límite de memoria: 65536K | |
Envíos totales: 31958 | Aceptado: 10375 |
Descripción
En un curso determinado, realizas n exámenes. Si obtiene ai de las preguntas bi correctas en la prueba i , su promedio acumulado se define como
.
Dados los puntajes de sus exámenes y un entero positivo k , determine qué tan alto puede llegar a su promedio acumulativo si se le permite reducir cualquier k de los puntajes de sus exámenes.
Suponga que realiza 3 pruebas con puntuaciones de 5/5, 0/1 y 2/6. Sin abandonar ninguna prueba, su promedio acumulado es
. Sin embargo, si abandona la tercera prueba, su promedio acumulado se convierte en .
Aporte
El archivo de prueba de entrada contendrá varios casos de prueba, cada uno con exactamente tres líneas. La primera línea contiene dos números enteros, 1 ≤ n ≤ 1000 y 0 ≤ k < n . La segunda línea contiene n números enteros que indican ai para todo i . La tercera línea contiene n enteros positivos que indican bi para todo i . Se garantiza que 0 ≤ ai ≤ bi ≤ 1.000.000.000. El final del archivo está marcado por un caso de prueba con n = k = 0 y no debe procesarse.
Producción
Para cada caso de prueba, escriba una sola línea con el promedio acumulativo más alto posible después de descartar k de los puntajes de la prueba dados. El promedio debe redondearse al número entero más cercano.
Entrada de muestra
3 1 5 0 2 5 1 6 4 2 1 2 7 9 5 6 7 9 0 0
Salida de muestra
83 100
Pista
Para evitar ambigüedades debidas a errores de redondeo, las pruebas de los jueces se han construido de modo que todas las respuestas estén al menos a 0,001 de un límite de decisión (es decir, se puede suponer que el promedio nunca es 83,4997).
Ideas:
en tema
Para simplificar, intenta encontrar la x que sea menor que .
El punto final izquierdo es 0 y el punto final derecho es la suma acumulativa de ai. Esta es una búsqueda binaria eficiente.
Al realizar la dicotomía, también es necesario considerar si es monótona.
#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
struct Pair {
int a, b;
double y;
}p[1005];
bool cmp(Pair a, Pair b) {
return a.y > b.y; // 从大到小
}
int n, k;
bool check(double x) {
for (int i = 0; i < n; i++) {
p[i].y = p[i].a * 1.0 - x * p[i].b; // y = a - x*b 在x轴小点的值
}
sort(p, p + n, cmp);
double f = 0;
for (int i = 0; i < k; i++) f += p[i].y;
return f < 0;
}
int main() {
while (cin >> n >> k, n + k) {
k = n - k; // 选出 k 对
for (int i = 0; i < n; i++) cin >> p[i].a;
for (int i = 0; i < n; i++) cin >> p[i].b;
double L = 0, R = 0;
for (int i = 0; i < n; i++) R += p[i].a;
for (int i = 0; i < 50; i++) {
double mid = L + (R - L) / 2;
if (check(mid)) R = mid;
else L = mid;
}
printf("%d\n", (int)(100 * (L + 0.005)));
}
return 0;
}