思路:
不妨假设最坏情况下回报为mid,假设在每个结果上的投入分别是x[1],x[2]...x[n],那么则有min(x[1] * a[1], x[2] * a[2] .. x[n] * a[n]) >= mid, 即对于任意的 i ,有x[i] * a[i] >= mid,所以x[1] >= mid / a[1] x[2] >= mid / a[2] ... x[n] >= mid / a[n]。因为X = x[1] + x[2] + .. x[n] 那么如果mid / a[1] + ... mid / a[n] <= X,说明最坏情况下至少可以取得的回报为mid(每个投入为x[1]...x[n]即可,剩余的钱随便乱搞)。否则说明总钱数不能满足这样情况。因此,如果mid满足条件,即mid / a[1] + ... + mid / a[n] = mid * (1 / a[1] + .. 1 / a[n]) <= X,对于任意P <= mid的数,必然满足P * (1 / a[1] + .. 1 / a[n]) <= X 如果mid不满足条件,那么mid * (1 / a[1] + .. 1 / a[n]) > X,对于任何大于mid的数Q,Q * (1 / a[1] + ... 1 / a[n]) > mid * (1 / a[1] + .. 1 / a[n]) > X。 所以mid具有单调性,因此二分mid即可。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=110;
const double exp=1e-8;
int n;
double a[maxn],x;
bool can(double mid)
{
double sum=0;
for(int i=0;i<n;i++)
sum+=mid/a[i];
if(sum<=x)return true;
else return false;
}
void solve()
{
double l=0,r=1000000.0,mid,ans;
while(l+exp<=r)
{
mid=(l+r)/2;
if(can(mid))
{
ans=mid;
l=mid+exp;
}
else r=mid-exp;
}
printf("%.2lf\n",ans);
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)scanf("%lf",&a[i]);
scanf("%lf",&x);
solve();
}
return 0;
}