Loading

CF2023D Many Games 题解

赛时被创四了。

思路

考虑我们什么时候合并会比原来优。

例如,我们现在要合并 \(p_1,w_1\)\(p_2,w_2\),同时保证,\(w_1\ge w_2\)

那么有:

\[\frac{p_1}{100}\times w_1\le \frac{p_1}{100}\times \frac{p_2}{100}\times (w_1+w_2) \]

\[\frac{p_2}{100}\times w_2\le \frac{p_1}{100}\times \frac{p_2}{100}\times (w_1+w_2) \]

转换一下:

\[\frac{p_1}{100}\times (\frac{p_2}{100}\times (w_1+w_2)-w_1)\ge 0 \]

\[\frac{p_2}{100}\times (\frac{p_1}{100}\times (w_1+w_2)-w_2)\ge0 \]

由于 \(p1,p2\ge 1\)

\[\frac{p_2}{100}\times (w_1+w_2)-w_1\ge 0 \]

\[\frac{p_1}{100}\times (w_1+w_2)-w_2\ge0 \]

所以:

\[\frac{100-p_2}{100}w_1\le \frac{p_2}{100}w_2\ \]

\[\frac{p_1}{100}w_1\ge \frac{100-p_1}{100}w_2 \]

消掉系数。

\[\frac{(100-p_1)w_2}{p_1}\le w_1\le \frac{p_2w_2}{100-p_2}\\ \]

这个不等式可以推出 \(w_1\le p_2w_2\)

这告诉我们当 \(w\) 的和超过 \(p_2w_2\) 时,合并一定不优。

那么去掉 \(p=100\) 的情况,所有选出的 \(w\) 一定小于等于 \(4\times 10^5\)

这种情况下,我们可以做一个背包。

复杂度是 \(O(nV)\) 的。

接着,我们可以发现,有很多二元组是没有用的。

具体来说,对于 \(p\) 相同的二元组,我们按 \(w\) 从大到小排序以后。我们采用的一定是一段前缀。

而这一堆前缀的总和也没有很多,大约是 \(99\times \ln99\)

因此我们可以在加入一个二元组的时候判断一下是否对背包产生了贡献,如果没有,那么之后相同的 \(p\) 就没有必要加入背包了。

Code

/*
  ! 前途似海,来日方长。
  ! Created: 2024/10/20 18:08:39
*/
#include <bits/stdc++.h>
using namespace std;

#define x first
#define y second
// #define int long long
#define mp(x, y) make_pair(x, y)
#define eb(...) emplace_back(__VA_ARGS__)
#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)
inline void JYFILE19();

using i64 = long long;
using pii = pair<int, int>;

bool ST;
const int N = 1e6 + 10;
const int mod = 998244353;

int n, m, vs[N];
double sm;
double ns;
double f[N];
struct Node {
  int p, w;
  inline bool operator<(const Node&tmp) const { return w > tmp.w; } 
} d[N];

signed main() {
  JYFILE19();
  cin >> n;
  fro(i, 1, n) cin >> d[i].p >> d[i].w;
  sort(d + 1, d + n + 1);
  f[0] = 1;
  fro(i, 1, n) {
    if (d[i].p == 100) sm += d[i].w;
    else {
      if (vs[d[i].p]) continue;
      int h = d[i].p * d[i].w / (100 - d[i].p);
      double r = d[i].p / 100.;
      bool flag = 0;
      pre(j, h, 0)
        if (f[j + d[i].w] < f[j] * r)
          f[j + d[i].w] = f[j] * r, flag = 1;
      if (flag == 0) {
        vs[d[i].p] = 1;
      }
    }
  }
  fro(i, 0, 400000) ns = max(ns, (i + sm) * f[i]);
  printf("%.9lf\n", ns);
  return 0;
}

bool ED;
inline void JYFILE19() {
  // freopen(".in", "r", stdin);
  // freopen(".out", "w", stdout);
  srand(random_device{}());
  ios::sync_with_stdio(0), cin.tie(0);
  double MIB = fabs((&ED - &ST) / 1048576.), LIM = 32;
  cerr << "MEMORY: " << MIB << endl, assert(MIB <= LIM);
}
posted @ 2024-10-22 11:14  JiaY19  阅读(38)  评论(0)    收藏  举报