BZOJ 4030: [HEOI2015]小L的白日梦
4030: [HEOI2015]小L的白日梦
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 172 Solved: 39
[Submit][Status][Discuss]
Description
在某一天,你有了一个女性朋友。
Input
第一行有一个非负整数t,表示一共有t组数据。
Output
一共t行,对于每组数据输出使她感到失落的最小期望次数,四舍五入保留6位小数。
Sample Input
1 2
0/1 3
1 2
1/1 3
1 2
1/2 3
Sample Output
0.000000
0.250000
【样例说明】
考虑第三组数据,因为只有一个项目所以只好每天都安排这个。
在第一天之前她总是不高兴的,一共有:
第一天不高兴,第二天也不高兴、
第一天高兴,第二天不高兴、
第一天不高兴,第二天高兴、
第一天不高兴,第二天也不高兴,
这四种情况,又因为每天的项目让她高兴或者是不高兴的概率都是0.5,因此这四种情况是等概率发生的。
只有在第二种情况下,她会感到失落一次。
因此答案是(1*1+0*3)/4=0.25.
HINT
对于100%的数据,n<=105,k<=109,数据组数不会太多,大概不超过10组,数据保证分数有意义并且∑c[i]>=k。
Source
这种网上没有题解的题,必须要写一发骗骗访问量哈~~~
我上午做这道题的时候,网上没有专门的题解,只有jiry前辈的一篇HEOI2015系列题解可做参考,所以我就无耻地抄代码啦~~~
先转一下jiry的题解内容——
【D2T1】小L的白日梦
这题我在网上找不到题解..但是为了访问量我也是只好硬上了...我的算法建立在以下假设之上:
1.一定存在最优解每一天不高兴的概率是单调不增的。
2.一定存在最优解它选取的项目是所有项目按照不高兴的概率排序后的前缀一段加上后缀一段。
3.每一次选取的项目种类只有三种可能的情况:选了1个,全部选完,其他。且处于第三种状态的至多一个。
不要问我是怎么知道这三个假设的..我连最基本的假设1都不会证明..这些全部都是在各种暴力求证之后得到了..这A的实在是6的不行..
知道了这些假设就很简单了..假设第三种状态的是取在后缀中的,那么枚举选取前缀最右端的位置,后缀最左端的位置单调不增,扫一下就好了,反过来也是一样。
我看了看这三个假设,如果是正确的话那么jiry的做法确实很棒棒,但是我只能证明第一个,好菜啊。下午Monster__Yi来嘲讽我了,“这么水的题,你都不会证明?还考什么NOI,HEOI你就可以滚粗了!” 唔唔唔,宝宝心里苦啊……
然后在小天天(Monster_Yi)的帮助下,我(ta)证明了另外两个性质,所以记录一下,趁着他还没写赶紧骗访问量,23333
性质1:一定存在最优解每一天不高兴的概率是单调不增的
这个性质最显然,证明方法就是列个式子,用$a_i$表示排序后第i个项目的不高兴概率,那么当前的期望值就是
$$P=(1-a_0)a_1+(1-a_1)a_2+(1-a_2)a_3+...+(1-a_{n-1})a_n$$
然后考虑交换两个项,$a_i$和$a_j$,现在的期望值变成了
$$P'=(1-a_0)a_1+...+(1-a_{i-1})a_j+(1-a_j)a_{i+1}+...+(1-a_{j-1})a_i+(1-a_i)a_{j+1}$$
根据$a_{i-1} \gt a_i \gt a_{i+1} \gt a_{j-1} \gt a_j \gt a_{j+1}$,
我们有
$$P-P'=(1-a_{i-1})a_i+(1-a_i)a_{i+1}+(1-a_{j-1})a_j+(1-a_j)a_{j+1}-(1-a_{i-1})a_j-(1-a_j)a_{i+1}-(1-a_{j-1})a_i-(1-a_i)a_{j+1}=(1-a_{i-1})(a_i-a_j)-a_{i+1}(a_i-a_j)-(1-a_{j-1})(a_i-a_j)+a_{j+1}(a_i-a_j)=(a_i-a_j)(-a_{i+1}-a_{i+1}+a_{j-1}+a_{j+1}) \lt 0$$
所以$P \lt P'$,即按照不高兴概率递减的顺序排列,期望更优。
性质2:一定存在最优解它选取的项目是所有项目按照不高兴的概率排序后的前缀一段加上后缀一段
这个性质也是列式子证明的。我们不妨设$A \lt B \lt C \lt D$,代表四个项目(按照不高兴概率递减的顺序排列),我们用$a,b,c,d$表示其不高兴概率,有$a\gt b\gt c\gt d$。
我们设原情况是我们从整个序列中选取了三段——[1,A],B,[D,N]。
我们设新情况是我们从整个序列中选取了三段——[1,A],C,[D,N]。
原情况的期望是$(1-a)b+(1-b)d$。
新情况的期望是$(1-a)c+(1-c)d$。
当新情况优于原情况,必然有$(1-a)b+(1-b)d>(1-a)c+(1-c)d$
解得$a+d>1$,这个就说,当$a+d>1$时,中间的点会往右靠,直到靠到后缀上;反之,中间的点会往前靠,直到靠到前缀上。所以,前缀和后缀中间不会有点被选中。
性质3:每一次选取的项目种类只有三种可能的情况:选了1个,全部选完,其他,且处于第三种状态的至多一个
前两个性质我们都是把所有项目拆成$c_i$个单独的项目考虑的,并且已经可以解决$\sum c_i \leq 10^6$时的问题了。现在我们考虑把相同项目看成一个连续的块,会有什么新的性质。
可喜可贺的是,这个性质不用列式子了,随便一想就能发现。
如果我们当前前缀的最后一个块(也就是最后一种项目)只选取了一个点,后缀的最前一个块选取了若干个点。
然后我们发现把后缀的一个名额送给前缀的最后一个块,会使期望值减少$delta$,使期望值变优。那么,我们可以说,在后缀的最后一个块露出尾巴(也就是被削减得只剩一个点)之前,我们每把一个后缀名额送给前缀,都会使得期望减少$delta$。所以我们定然会把后缀不断减少,直到其最前一个块只剩一个点为止,此时再削减最后一个块,产生的代价将不再是$delta$,所以不能继续无脑转移名额了。
可见,前缀和后缀的最后(前)一个块在某些情况只会选一个点,但绝不会同时选若干个点,都不是1而且都没有全选。
代码还是抄的jiry前辈的,毕竟我的代码功底可是非常差的。
#include <bits/stdc++.h>
using namespace std;
typedef long long lng;
typedef long double ldb;
struct data {
int cnt; ldb val;
inline data(void) {};
inline data(int a, ldb b)
: cnt(a), val(b) {};
inline void read(void) {
static int a, b;
scanf("%d/%d", &a, &b);
val = (ldb)a / b;
scanf("%d", &cnt);
}
}A[], B[];
inline bool operator < (const data &a, const data &b) {
return a.val > b.val;
}
int n, m, cas, tot;
inline ldb calc(void) {
ldb ret = 1E18, sum = ;
lng now = , rem = m;
for (int i = n; i; --i)
sum += (B[i].cnt - ) * B[i].val * ( - B[i].val) + ( - B[i].val) * B[i + ].val, rem -= B[i].cnt;
for (int i = ; i <= n; ++i ) {
rem -= B[i].cnt;
while (now <= n && rem <= )
sum -= (B[now].cnt - ) * B[now].val * ( - B[now].val) + ( - B[now].val) * B[now + ].val, rem += B[now++].cnt;
if (rem <= )break;
sum += (B[i].cnt - ) * B[i].val * ( - B[i].val) + ( - B[i - ].val) * B[i].val;
ret = min(ret, sum + (rem - ) * B[now - ].val * ( - B[now - ].val) + ( - B[now - ].val) * B[now].val + ( - B[i].val) * B[now - ].val);
}
rem = m, sum = ;
for (int i = ; i <= n; ++i) {
int mn = min(rem, (lng)B[i].cnt);
if(!mn)break; else rem -= mn, sum += (mn - ) * B[i].val * ( - B[i].val) + ( - B[i - ].val) * B[i].val;
}
return ret = min(ret, sum);
}
signed main(void) {
for (scanf("%d", &cas); cas--; ) {
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i) {
A[i].read(); if (!A[i].cnt)--i, --n;
}
sort(A + , A + n + ); tot = ;
for (int i = ; i <= n; ++i) {
B[++tot] = data(, A[i].val);
if (--A[i].cnt) {
if (A[i].cnt > )
B[++tot] = data(A[i].cnt - , A[i].val);
B[++tot] = data(, A[i].val);
}
}
B[].val = , B[(n = tot) + ].val = ;
ldb ans = calc();
for (int i = ; i <= n; ++i)
if (i < n + - i)swap(B[i], B[n + - i]);
for (int i = ; i <= n; ++i)B[i].val = - B[i].val;
ans = min(ans, calc());
printf("%.6lf\n", (double)fabs(ans));
}
}
@Author: YouSiki
BZOJ 4030: [HEOI2015]小L的白日梦的更多相关文章
- 【BZOJ4030】[HEOI2015]小L的白日梦
[BZOJ4030][HEOI2015]小L的白日梦 题面 BZOJ 洛谷 题解 要求的是最小的不开心连续段的期望. 然后发现自己就不会做了. 然后就可以来抄题解啦. 首先来猜性质: 第一个,一定是按 ...
- HEOI2015小L的白日梦
题面链接 洛咕 sol 为什么网上面只有神仙题解啊!!! 引起我这种蒟蒻不适QAQ. 性质证明留给巨佬 然后我只贴性质了QwQ. 1.一定存在最优解每一天不高兴的概率是单调不增的. 2.一定存在最优解 ...
- P4110 [HEOI2015]小L的白日梦
传送门 题解 //minamoto #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef l ...
- bzoj 4031: [HEOI2015]小Z的房间 轮廓线dp
4031: [HEOI2015]小Z的房间 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 98 Solved: 29[Submit][Status] ...
- BZOJ 4031: [HEOI2015]小Z的房间 高斯消元 MartixTree定理 辗转相除法
4031: [HEOI2015]小Z的房间 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4031 Description 你突然有了一个 ...
- bzoj4030【HEOI2015】小L的白日梦
题意:http://www.lydsy.com/JudgeOnline/problem.php?id=4030 sol :orz Yousiki http://www.cnblogs.com/you ...
- 【刷题】BZOJ 4031 [HEOI2015]小Z的房间
Description 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着. ...
- BZOJ 4031: [HEOI2015]小Z的房间 Matrix-Tree定理
题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=4031 题解: Matrix-tree定理解决生成树计数问题,其中用到高斯消元法求上三角矩 ...
- BZOJ:4031: [HEOI2015]小Z的房间
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1103 Solved: 536[Submit][Status][Discuss] Descripti ...
随机推荐
- WPS客户端更新日志留着备用
WPS Office (10.1.0.7520)==========================================新增功能列表------------WPS文字1 拼写检查:新增“中 ...
- Android系统的三种分屏显示模式
Google在Android 7.0中引入了一个新特性——多窗口支持,允许用户一次在屏幕上打开两个应用.在手持设备上,两个应用可以在"分屏"模式中左右并排或上下并排显示.在电视设备 ...
- JAVA 递归实现从n个数中选取m个数的所有组合
这周Java课程有个小作业:Java递归实现从n个数中选取m个数的所有组合 代码如下: //其中 n 取 1,2,3,4,5 五个数, m 取 3 package javaText; public c ...
- 字符是否为SQL的保留字
要想知道字符是否为MS SQL Server保留字,那我们必须把SQL所有保留字放在一个数据集中.然后我们才能判断所查找的字符是否被包含在数据集中. MS SQL Server保留字: ) = 'ad ...
- luajit官方性能优化指南和注解
luajit是目前最快的脚本语言之一,不过深入使用就很快会发现,要把这个语言用到像宣称那样高性能,并不是那么容易.实际使用的时候往往会发现,刚开始写的一些小test case性能非常好,经常毫秒级就算 ...
- 【记录】IntelliJ IDEA—IDEA2018-2019激活
摘要 最智能的java ide [有能力请支持正版] 1.将 0.0.0.0 account.jetbrains.com 和 0.0.0.0 www.jetbrains.com添加到 host ...
- Windows server 2008R2远程桌面3389端口修改方法技巧
windows server的服务器远程桌面默认端口号是3389,在工作中经常使用远程桌面连接服务器,但是这也是常常被黑客利用的端口号,但是如何修改掉默认端口,预防被黑客利用呢? 可以如下操作配置:很 ...
- Dijango学习_02_极简本地博客创建
二. Python 自带SQLite3数据库,Django默认使用SQLite3数据库,如果使用其它数据库可以在settings.py文件中设置. DATABASES = { 'default': { ...
- SQLServer数据事务日志操作
日志备份 (log backup) 包括以前日志备份中未备份的所有日志记录的事务日志备份. (完整恢复模式) 使用SSMS数据库管理工具备份事务日志 1.连接数据库,选择数据库->右键点击-&g ...
- 我的第一个python web开发框架(35)——权限数据库结构设计
接下来要做的是权限系统的数据库结构设计,在上一章我们了解了权限系统是通过什么来管理好权限的,我们选用其中比较常用的权限系统来实现当前项目管理要求. 下面是我们选择的权限系统关系模型: 从以上关系可以看 ...