ACdream1066

来源:互联网 发布:react js 中文教程 编辑:程序博客网 时间:2024/05/17 02:41

思路:因为我们要使最坏的情况获得钱最多,肯定要让不管哪一个赢都能得到一样的钱V。在总钱数X一定的情况下,如果有某个赢之后获得的钱大于V,那么肯定有某个赢之后的钱少于V,如果是其他都输了而这个赢钱少的赢了那么得到的钱就比V少。题目中问的就是最坏情况下的最大收益(最大化平均值),所以我们应该让不管哪个赢获得钱都一样的钱V。那么怎么求V呢?有两种思路:

①我们可以二分这个数字,然后通过判断在回报都为V时的投入跟实际总钱数X的关系确定如何缩小区间。

②其实我们可以发现是有规律的,假设平均回报为v,每个赔率为a[i],总钱数为X,我们可以得到下面这个式子

化简得所以

X跟a[1~n]都已知,所以答案V可以求出来,然后保留个两位小数输出就可以了。

公式法:

#include<bits/stdc++.h>using namespace std;int main(){int n;double a[105],x,v;while(~scanf("%d",&n)){for(int i = 0; i < n; i++) scanf("%lf",&a[i]);scanf("%lf",&x);v = 0.0;    for(int i = 0; i < n; i++) v += 1 / a[i];      printf("%.2lf\n",x / v);}return 0;}


二分法:

这个首先二分是一个有关精度的二分问题,所以结束条件为l-r<eps,每次缩区间也不能让L或R等于m±1了,而是等于M±eps。因为我们二分的是回报,所以最小回报L=0.00,最大回报等于总钱数乘赔率的最大值,即R = ,如果再去找太麻烦了,题意中说到了a的取值范围为[0.01,100],所以我们直接初始R=X*100就可以了。

#include<bits/stdc++.h>using namespace std;const double eps=1e-8;int n;double a[105],x,v;double check(double m){double sum = 0.0;for(int i = 0; i < n; i++){    sum += m / a[i];}return sum;}int main(){while(~scanf("%d",&n)){for(int i = 0; i < n; i++) scanf("%lf",&a[i]);scanf("%lf",&x);    double l = 0.0,r = x * 100,m = l + (r - l) / 2.0;    while(r - l > eps)    {if(check(m) < x) l = m + eps;    else if(check(m) > x) r = m - eps;else break;m = l + (r - l) / 2.0;}    printf("%.2lf\n",m);}return 0;}





原创粉丝点击