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;
}
相关推荐
fpcc6 小时前
c++编程实践—堆和栈越界调试
c++
yi0116 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
weiabc7 小时前
MSYS2 UCRT64 + g++ C++ 中文输出乱码 完整全过程
c++
灯澜忆梦8 小时前
【面向对象编程C++】| 基础语法
java·c++·算法
小蒋观天下9 小时前
专项方案:大场景港口AI安防、多干扰环境下的算法调优与落地实操
人工智能·深度学习·算法·安全·机器学习·计算机视觉·ai大模型
Evand J9 小时前
【电机滤波例程5】渐消因子自适应扩展卡尔曼滤波(EKF),MATLAB。PMSM负载突变下的状态估计。附下载链接
算法·matlab
H.莓飛9 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
好想像大佬一样能够ak所有10 小时前
Leetcode35.搜索插入位置
数据结构·算法·leetcode
aqiu11111110 小时前
【C++算法打怪专栏】LeetCode 165. 比较版本号(双指针与字符串流法)
c++·算法·leetcode
黄金龙PLUS10 小时前
如何基于置换算法来设计对称加密算法
算法·网络安全·密码学·哈希算法·同态加密