CF2023D

CF2023D

Tags:

  • DPStateShrink 动态规划状态缩减,只计算有效状态

题解:

这个题目的问题可以转化为:

选择一个子集 ,最大化他的贡献:

E=(∑iwi)∏ipi100 E=(\sum_{i}w_i) \prod_{i}\frac{pi}{100} E=(i∑wi)i∏100pi

显然当p为100时 ,一定会全选

当p不是100时:

我们令

Eodd=W∗Q E_{odd}=W*Q Eodd=W∗Q

假如我们删除游戏 qiq_iqi wiw_iwi :

Enew=(W+wi)Q∗qi E_{new}=(W+w_i){Q}*{q_i} Enew=(W+wi)Q∗qi

如果删除后更好 那么有

(W+wi)Q∗qi<W∗Qwi∗qi<W∗(1−qi) (W+w_i){Q}*{q_i}<W*Q\\ w_i*q_i<W*(1-q_i)\\ (W+wi)Q∗qi<W∗Qwi∗qi<W∗(1−qi)

根据

wi∗pi<=200000那么W∗(100−pi)>200000 w_i*p_i<=200000\\ 那么\\ W*(100-p_i)>200000 wi∗pi<=200000那么W∗(100−pi)>200000

因此最终W的上界也在200000左右

由于w是存在上界的 ,而且根据我们的直觉,因为概率是累乘的,因此最终选择的物品不会很多,不然累乘后权重会很小

对于同一个p,显然我们只会选择w最大的几个前缀元素

假设我们选择了c个概率为p的元素,那么设其中权重最小的为w_c

如果删除这个最小的元素

原来的期望为WQ 删除后为(W-w_c)Q/q;

最优的时候删除不会更好

WQ>(W−wc)Q/qwc>W(1−q)因为c个wc的总权重为cwc那么W>=cwcwc>=cwc(1−q)c<=1/(1−q)c<=100/(100−p) WQ>(W-w_c)Q/q\\ w_c>W(1-q)\\ 因为c个w_c的总权重为cw_c 那么W>=cw_c\\ w_c>=cw_c(1-q)\\ c<=1/(1-q)\\ c<=100/(100-p) WQ>(W−wc)Q/qwc>W(1−q)因为c个wc的总权重为cwc那么W>=cwcwc>=cwc(1−q)c<=1/(1−q)c<=100/(100−p)

那么也就是说,每个p最多选择100/(100-p) 个元素最为候选

那么最多的元素个数就是

∑i=199100100−i约等于482 \sum_{i=1}^{99}\frac{100}{100-i} 约等于482 i=1∑99100−i100约等于482

因此我们只需要每个概率的若干个元素候选,然后进行01背包即可

令DPi表示W为i的时候,可以获得的最大的概率乘积

code:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2.1e5+5;


priority_queue<int>q[101];
double d[N];
void solve() {
    int n;
    cin>>n;
    d[0]=1;
    int k=0;
    for(int i=0;i<n;i++){
        int x,y;
        cin>>x>>y;
        if(x==100){
            k+=y;
        }else {
            q[x].push(y);
        }
    }
    for(int i=1;i<=99;i++){
        for(int y=100/(100-i);y&&q[i].size();y--){
            int x=q[i].top();
            q[i].pop();
            for(int j=N-1;j>=x;j--){
                d[j]=max(d[j],d[j-x]*i/100);
            }
        }
    }
    double ans=0;
    for(int i=0;i<N;i++){
        ans=max(ans,(i+k)*d[i]);
    }
    cout<<setprecision(7)<<fixed<<ans<<'\n';
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
   
    int t=1;
    // cin>>t;
    while(t--)solve();
    return 0;
}
相关推荐
小小帅呀19 分钟前
学习 VLA 第6天:SWIN VIT算法原理以及复现
学习·算法
Mr.Lu ‍21 分钟前
C++开发,使用openCV API对图片进行压缩
开发语言·c++·opencv
大鹏的NLP博客21 分钟前
ONNX Runtime CUDA 推理优化实战:破解 C++ 比 Python 慢 28 倍的假象
c++·onnx·推理优化
猎头南楼1 小时前
杭州算法工程师,偏大模型应用落地
算法
HugoStudio_SWAN1 小时前
【按键反馈】C++ 实现键盘烟花秀
开发语言·c++·学习·程序人生
间歇性努力持续性发呆的野生快乐选手1 小时前
二分模板(整型,浮点型)
数据结构·c++·算法
evans在进步1 小时前
LeetCode 189 轮转数组:三次反转为什么能实现右旋?
数据结构·算法·leetcode
豆沙沙包?1 小时前
函数重载/类和对象(P14-P60)
前端·算法