この問題では、目標とする比率を定め、その比率を実現できるかどうかを判定する方法を取ります。この判定作業を効率よく行うために二分探索を用います。
まず、比率を以上にできるかを考えてみましょう。数式で示すと以下のようになります。
これを式変形していきます。平均最大化の考え方に近いと思います。
このように変形出来ます。よって、個選んだ時、の総和が0以上になっていれば比率は以上に出来ると判定できます。
証明は省略しますが、は大きい順に選ぶのが最適です。
計算量については、二分探索で、判定でソートの部分がかかります。よって全体でとなります。
xxxxxxxxxx
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<double> e(n), p(n);
for(int i = 0;i < n; ++i){
cin >> e[i];
}
for(int i = 0;i < n; ++i){
cin >> p[i];
}
double ok = 0, ng = 1e18;
for(int ii = 0;ii < 100; ++ii){
double mid = (ok + ng)/2;
vector<double> a(n);
for(int i = 0;i < n; ++i){
a[i] = p[i] - mid*e[i];
}
sort(a.rbegin(), a.rend());
double sum = 0;
for(int i = 0;i < k; ++i){
sum += a[i];
}
if(sum >= 0){
ok = mid;
}else{
ng = mid;
}
}
printf("%.10f\n", ok);
return 0;
}