题目传送门(内部题38)


输入格式

每个输入文件包含多组测试数据。选手应当处理到文件结束($EOF$)
每一组数据包括$3$行。
第$1$行包含三个正整数$n,a,b$,表示有$n$只猫,$gyz$有$a$包干脆面和$b$包豆干。
第$2$行包含$n$个保留小数点后$3$位的实数$p_1,p_2...p_n$,$p_i$表示第$i$只猫喜欢干脆面的概率。
第$3$行包含$n$个保留小数点后$3$位的实数$q_1,q_2...q_n$,$q_i$表示第$i$只猫喜欢豆干的概率。


输出格式

每组测试数据输出一行,表示最优策略下期望捉到的猫数。保留小数点后$3$位输出。


样例

样例输入:

3 2 2
1.000 0.000 0.500
0.000 1.000 0.500
4 1 3
0.100 0.500 0.500 0.600
0.100 0.500 0.900 0.400
3 2 0
0.412 0.198 0.599
0.612 0.987 0.443

样例输出:

2.75000
2.16000
1.01100


数据范围与提示

$T$表示测试数据组数,$\sum n$表示输入文件中所有数据的$n$之和。
$100\%$的数据,$T\leqslant 10,\sum n$不超过$100,000$。
$100\%$的数据,$0\leqslant a\leqslant n,0\leqslant b\leqslant n$。
每个测试点的$n,T$的范围见下表。


题解

原题是$codeforces 794E$,这道题增加了数据范围i提高了难度(原题官方题解$\Theta(n^2\log n)$时间复杂度).

为了方便,以下干脆面简称辣条……

对于这道题,我们期望抓到猫的个数即为猫喜欢的概率。

那么对于一只猫,分为四种情况:

  $\alpha.$不投喂,贡献为$0$。

  $\beta.$投喂辣条,贡献为$p_i$。

  $\gamma.$投喂豆干,贡献为$q_i$。

  $\delta.$都投喂,贡献为$p_i+q_i-p_i\times q_i$(注意可以理解为减去了都喜欢的概率)。

先来考虑$\Theta(n\times a\times b)$的$DP$。

定义$dp[i][j][k]$表示到了第$i$只猫,用了$j$个辣条,$k$个豆干的最大值。

那么状态转移方程即为:
$dp[i][j][k]=\max(dp[i-1][j][k],dp[i-1][j-1][k-1]+p_i+q_i-p_i\times q_i,dp[i-1][j-1][k]+p_i,dp[i-1][j][k-1]q_i)$

需要注意的是空间问题,小心不要$MLE$,不然你就$TM$双$LE$了。

不知道有没有人还记得这道题[BZOJ2654]:tree(Kruskal+WQS二分),当然我说的是正解,也就是$WQS$(忘情水)二分。

那么这道题我们也可以这样考虑,先将所有的辣条都加一个额外的代价,然后用花费的辣条跟总辣条数做比较;豆干同理。

时间复杂度:$\Theta(n\log^2n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,a,b;
double p[100001],q[100001];
double dp[100001],fp[100001],fq[100001];
void calc(double x,double y)
{
for(int i=1;i<=n;i++)
{
dp[i]=dp[i-1];
fp[i]=fp[i-1];
fq[i]=fq[i-1];
if(dp[i-1]+p[i]>dp[i]+x)
{
dp[i]=dp[i-1]+p[i]-x;
fp[i]=fp[i-1]+1;
fq[i]=fq[i-1];
}
if(dp[i-1]+q[i]>dp[i]+y)
{
dp[i]=dp[i-1]+q[i]-y;
fp[i]=fp[i-1];
fq[i]=fq[i-1]+1;
}
if(dp[i-1]+p[i]+q[i]-p[i]*q[i]>dp[i]+x+y)
{
dp[i]=dp[i-1]+p[i]+q[i]-p[i]*q[i]-x-y;
fp[i]=fp[i-1]+1;
fq[i]=fq[i-1]+1;
}
}
}
double dichotomize2(double mid1)
{
double lft=0,rht=1;
while(rht-lft>1e-8)
{
double mid2=(lft+rht)/2;
calc(mid1,mid2);
if(fq[n]>b)lft=mid2;
else rht=mid2;
}
return rht;
}
pair<double,double> dichotomize1()
{
double lft=0,rht=1;
while(rht-lft>1e-8)
{
double mid=(lft+rht)/2;
calc(mid,dichotomize2(mid));
if(fp[n]>a)lft=mid;
else rht=mid;
}
double flag=dichotomize2(rht);
calc(rht,flag);
return make_pair(rht,flag);
}
int main()
{
while(~scanf("%d%d%d",&n,&a,&b))
{
for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
for(int i=1;i<=n;i++)scanf("%lf",&q[i]);
pair<double,double> flag=dichotomize1();
printf("%.3lf\n",dp[n]+a*flag.first+b*flag.second);
}
return 0;
}

rp++

[CSP-S模拟测试]:赤(red)(WQS二分+DP)的更多相关文章

  1. 「学习笔记」wqs二分/dp凸优化

    [学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...

  2. [CSP-S模拟测试]:中间值(二分)

    题目背景 $Maxtir$喜欢序列的中间值. 题目传送门(内部题127) 输入格式 第一行输入两个正整数$n,m$,其中$m$是操作和询问次数. 接下来两行每行输入$n$个非负整数,每一行分别表示两个 ...

  3. [CSP-S模拟测试]:二叉搜索树(DP+贪心)

    题目传送门(内部题99) 输入格式 第一行一个整数$n$,第二行$n$个整数$x_1\sim x_n$. 输出格式 一行一个整数表示答案. 样例 样例输入: 58 2 1 4 3 样例输出: 数据范围 ...

  4. [CSP-S模拟测试]:装饰(状压DP)

    题目传送门(内部题114) 输入格式 第一行一个正整数$n$. 接下来一行$n-1$个正整数,第$i$个数为$f_{i+1}$. 接下来一行$n$个数,若第$i$个数为$0$则表示林先森希望$i$号点 ...

  5. [CSP-S模拟测试]:城市游戏(图论+DP)

    题目传送门(内部题109) 输入格式 第一行,两个整数$n,m$. 接下来$m$行,每行三个整数$u,v,l$,描述了一条道路连接的两个路口的编号以及道路的长度. 输出格式 输出一行一个整数,为所求的 ...

  6. [CSP-S模拟测试]:取石子(博弈论+DP)

    题目描述 有三堆石子,它们的石子个数分别为$x,y,z$.$A$和$B$正在博弈,由$A$先手,双方轮流操作.每次操作是指,选择若干堆($1-3$堆)石子,从中各取出相同数量的石子(不能$1$个都不取 ...

  7. [CSP-S模拟测试]:旅行计划(分块+DP)

    题目传送门(内部题83) 输入格式 第一行两个整数$n,m$ 接下来$m$行,每行三个整数,$u,v,w$,表示从$u$到$v$有一条权值为$w$的边 接下来一行有一个整数$q$,表示$q$天 接下来 ...

  8. [CSP-S模拟测试]:糊涂图(概率DP)

    题目传送门(内部题76) 输入格式 第一行输入三个空格隔开的整数$n,m,s$表示随机加一条边之前的糊涂图的点数,边数,以及起点的编号. 接下来$m$行,每行两个空格隔开的整数$a,b$表示从$a$到 ...

  9. [CSP-S模拟测试]:简单的期望(DP)

    题目描述 从前有个变量$x$,它的初始值已给出. 你会依次执行$n$次操作,每次操作有$p\%$的概率令$x=x\times 2$,$(100−p)\%$的概率令$x=x+1$. 假设最后得到的值为$ ...

随机推荐

  1. k-近邻算法(kNN)完整代码

    from numpy import *#科学计算包 from numpy import tile from numpy import zeros import operator #运算符模块 impo ...

  2. [bzoj3462]DZY Loves Math II (美妙数学+背包dp)

    Description Input 第一行,两个正整数 S 和 q,q 表示询问数量. 接下来 q 行,每行一个正整数 n. Output 输出共 q 行,分别为每个询问的答案. Sample Inp ...

  3. Shell逻辑运算符及表达式

    一. 运算符总结说明 1. 条件运算符 运算符号 代表意义 应用 说明 = 等于 整型或字符串比较: str1 = str2 字符串str1 和字符串str2 相等时返回真,如果在[]中,只能是字符串 ...

  4. Python3学习(18)--偏函数(Partial) --转载存地址

    由于最近出差,没有时间更,  倒不是忙,而是费心,项目其实并不难,主要是涉及钱的地方谈技术略显苍白:没有技术解决不了的问题,但是钱没到位,没人愿意无偿给你提供技术,算是停更一周后的,吐槽吧. 赶上今天 ...

  5. 使用matplotlib画出log的图像

    以下内容是学习笔记,若有侵权,立即删除! import math import matplotlib.pyplot as plt import numpy as np if __name__ == ' ...

  6. HTML块,含样式的标签

    HTML块,含样式的标签 html块 div标签 块元素,表示一块内容,没有具体的语义. span标签 行内元素,表示一行中的一小段内容,没有具体的语义. 含样式和语义的标签 em标签 行内元素,表示 ...

  7. java基础知识-基本概念

    1.1 java语言有哪些优点? 1.java语言为纯面向对象的语言. 2.平台无关性.java语言的优点便是“一次编译,到处执行”.编译后的程序不会被平台所约束,因此java语言有很好的移植性. 3 ...

  8. js 模拟window.open 打开新窗口

    为什么要去模拟window.open() 打开一个 新的窗口呢,因为有些浏览器默认会拦截 window.open, 当需要函数中打开新窗口时,接可以使用a标签去模拟打开. /** * a模拟windo ...

  9. ant打包遇到的问题

    \build\build.xml:350: Problem: failed to create task or type foreach Cause: The name is undefined. A ...

  10. 53.Coin Change(找硬币)

    Level:   Medium 题目描述: You are given coins of different denominations and a total amount of money amo ...