CF2023D Many Games 题解

赛时被创四了。

思路#

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

例如,我们现在要合并 p1,w1p2,w2,同时保证,w1w2

那么有:

p1100×w1p1100×p2100×(w1+w2)

p2100×w2p1100×p2100×(w1+w2)

转换一下:

p1100×(p2100×(w1+w2)w1)0

p2100×(p1100×(w1+w2)w2)0

由于 p1,p21

p2100×(w1+w2)w10

p1100×(w1+w2)w20

所以:

100p2100w1p2100w2 

p1100w1100p1100w2

消掉系数。

(100p1)w2p1w1p2w2100p2

这个不等式可以推出 w1p2w2

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

那么去掉 p=100 的情况,所有选出的 w 一定小于等于 4×105

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

复杂度是 O(nV) 的。

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

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

而这一堆前缀的总和也没有很多,大约是 99×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);
}

作者:JiaY19

出处:https://www.cnblogs.com/JiaY19/p/18492186

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   JiaY19  阅读(18)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示