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 ...
随机推荐
- Error occurred during initialization of VM Could not reserve enough space for 2097152KB object heap
ionic build Android后的报错问题 ionic 升级了splashscreen和statusbar的插件后,执行ionic build android会一直报打包错误.原因是过低的An ...
- ASP.NET Core 入门教程 2、使用ASP.NET Core MVC框架构建Web应用
一.前言 1.本文主要内容 使用dotnet cli创建基于解决方案(sln+csproj)的项目 使用Visual Studio Code开发基于解决方案(sln+csproj)的项目 Visual ...
- Linux简单配置SendMail发送邮件
本文简单整理了一下如何在Linux服务器上安装.配置SendMail发送邮件的步骤,此文不是配置邮件服务器,具体测试环境为CentOS Linux release 7.2.1511 (Core) ,如 ...
- Linux常见系统故障
Linux常见系统故障 1.修复MBR扇区故障 2.修复GRUB引导故障 3./etc/inittab文件丢失 4.遗忘root用户密码 5.修复文件系统 6.磁盘资源耗尽故障 一.修复MBR扇区故障 ...
- man -f/-k [keyword]在fedora 29 中报错nothing appropriate
我们在使用 man 手册的时候,可以使用man -f [keyword]去查询keyword的在线文档,但是这时候会报错:(图来源自网络) 这是因为我们还没有建立 man 手册的索引缓存: 我们可以使 ...
- 关于Java中IO流的练习
练习一:统计一个文件calcCharNum.txt中字母‘A’和'a'出现的总次数. package com.test; import java.io.File; import java.io.Fil ...
- 交替方向乘子法(ADMM)
交替方向乘子法(ADMM) 参考1 参考2 经典的ADMM算法适用于求解如下2-block的凸优化问题( 是最优值,令 表示一组最优解): Block指我们可以将决策域分块,分成两组变量, 这里面 都 ...
- 容易被误读的IOSTAT
iostat(1)是在Linux系统上查看I/O性能最基本的工具,然而对于那些熟悉其它UNIX系统的人来说它是很容易被误读的.比如在HP-UX上 avserv(相当于Linux上的 svctm)是最重 ...
- Python距离放弃拉近的day03
新的一天,依旧是内容补充,补充了数学没有的运算符,in和not in,就是判断in前面的东西是不是在后面的数据中,然后新课讲了平常最常用的字符串的方法,引号的里面全部都是字符串,在其中就会又如何判断这 ...
- (十)Modifying Your Data
Elasticsearch provides data manipulation and search capabilities in near real time. By default, you ...