比赛-ZR DAY4 (07 Aug, 2018)

A. 世界杯

假设法国队的赔率是 \(x\) ,则第 \(i\) 个人下注法国队的充要条件是
\[(x-1)\cdot a_{i}\cdot p_{i}-a_{i}\cdot (1-p_i)\geq 0\]
化简一下就是
\[x\geq\frac{1}{p_i}\]
类似的可以得出下注克罗地亚队的充要条件(假设赔率是 \(y\)
\[y\geq \frac{1}{1-p_i}\]
\(p_i\) 从大到小排序,显然下注法国队的是前缀 \([1, l]\) ,下注克罗地亚队的是一个后缀 \([r, n]\) 。彩票公司的利益是
\[\sum a[1...l]+\sum a[r...n]-max\left(\sum a[1...l]\cdot x, \sum a[r...n]\cdot y\right)\]
然后可以贪个心,当 \(max\) 内取前一项时考虑把 \(r\) 减去 \(1\) ,取后一项时考虑把 \(l\) 加上 \(1\) 。这样很可能不会改变 \(max\) 的取值,而使前面的式子的取值变大它就很好。就是这样。

#include <cstdio> 
#include <algorithm>

using namespace std;

const int _N = 1020000;

struct data {
    double a, p;
    bool operator < (const data &tmp) const
    {
        return p > tmp.p;
    }
} A[_N];

int main()
{
//  freopen("ex_a2.in", "r", stdin);
    int N;
    double ans = 0;
    scanf("%d", &N);
    for (int i = 1; i <= N; ++i) scanf("%lf%lf", &A[i].a, &A[i].p);
    sort(A+1, A+1+N);
    int l = 1, r = N;
    double suml = A[1].a, sumr = A[N].a;
    while (l <= N && r >= 1) {
        double x = 1/A[l].p, y = 1/(1-A[r].p);
        ans = max(ans, suml+sumr-max(suml*x, sumr*y));
        if (suml*x > sumr*y) sumr += A[--r].a;
        else suml += A[++l].a;
    }
    printf("%.6lf\n", ans);
    return 0;
}

B. 数组

C. 淘汰赛

猜你喜欢

转载自www.cnblogs.com/ghcred/p/9439178.html