Codeforces 442B. Andrey and Problem
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Andrey needs one more problem to conduct a programming contest. He has n friends who are always willing to help. He can ask some of them to come up with a contest problem. Andrey knows one value for each of his fiends — the probability that this friend will come up with a problem if Andrey asks him.
Help Andrey choose people to ask. As he needs only one problem, Andrey is going to be really upset if no one comes up with a problem or if he gets more than one problem from his friends. You need to choose such a set of people that maximizes the chances of Andrey not getting upset.
Input
The first line contains a single integer n (1 ≤ n ≤ 100) — the number of Andrey's friends. The second line contains n real numbers pi (0.0 ≤ pi ≤ 1.0) — the probability that the i-th friend can come up with a problem. The probabilities are given with at most 6 digits after decimal point.
Output
Print a single real number — the probability that Andrey won't get upset at the optimal choice of friends. The answer will be considered valid if it differs from the correct one by at most 10 - 9.
Examples
Input
4
0.1 0.2 0.3 0.8
Output
0.800000000000
Input
2
0.1 0.2
Output
0.260000000000
Note
In the first sample the best strategy for Andrey is to ask only one of his friends, the most reliable one.
In the second sample the best strategy for Andrey is to ask all of his friends to come up with a problem. Then the probability that he will get exactly one problem is 0.1·0.8 + 0.9·0.2 = 0.26.
题目大意
有\(n\)个人,你可以挑出一部分人来向他们要一道题,第\(i\)个人给你题的概率为\(p_i\),你只需要一道题,多了或少了你都不高兴。问在所有的选人方案里,有且仅有一道题的最大概率是多少?
题解
官方题解很明白不是很清楚你们为什么看不懂
先考虑选出的集合$A = { p_1, p_2, p_3, \ldots , p_n } $
概率\(Ans\)为
\]
\]
\]
考虑向集合内添加一个新的元素\(p_x\),对答案的贡献为:
\]
看上去非常乱
记\(P = \prod_{j=1}^{n}(1-p_j),S=\sum_{i=1}^{n}\frac{p_i}{1-p_i}\)
上述式子改写成
\]
\]
\]
发现:
引理1:唯有当\(S < 1\)时,\(x\)才会加入集合
那么对于所有满足\(S < 1\)的元素,我们加哪个更好呢?
考虑两个元素\(i,j,i\neq j\),他们的贡献差为:
\]
\]
\]
由此得到:
引理2:当元素\(i\)比\(j\)更优时,当且仅当\(\Delta ^{'}> 0\),即\(p_i > p_j\)
算法不难得出:按照\(p_i\)排序,不断往里加,一直加到\((1-S) \leq 0\)为止,即为答案
接下来通过上述结论来证明算法正确的充分性,即算法的是正确答案。
考虑反证法,假设最有答案集合为\(A\),存在元素\(i,j\),满足\(i \in A,j \notin B,p_i < p_j\),那我们把\(i\)从集合\(A\)中去掉,此时一定满足\((1-S) > 0\)(不然最优答案为啥要把\(i\)加进去呢)。根据引理1我们可以把\(j\)加进去,根引理2,加入\(j\)比加入\(i\)更优,与\(A\)为最优矛盾。所以\(j\)应该加入答案。
归纳一下算法就是对的了(唔)
此外还要加个特判
因为\(p_i = 1\)的时候S就挂了。。
所以如果出现\(1\),答案就是1,直接输出
其实我相当于把官方题解翻译了一遍,加了点自己的东西觉得更好理解
上述证明写法非常不严谨,大家自行脑补严谨的写法
只是做了点微小的工作,谢谢大家
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
inline int max(int a, int b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;}
inline void swap(int &x, int &y){int tmp = x;x = y;y = tmp;}
inline void read(int &x)
{
x = 0;char ch = getchar(), c = ch;
while(ch < '0' || ch > '9') c = ch, ch = getchar();
while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
double a[10000 + 10], S, P;
int n;
bool cmp(double a, double b)
{
return a > b;
}
int main()
{
read(n);
for(int i = 1;i <= n;++ i)
scanf("%lf", &a[i]);
std::sort(a + 1, a + 1 + n, cmp);
if(a[1] == 1)
{
printf("1");
return 0;
}
P = 1, S = 0;
for(int i = 1;i <= n;++ i)
{
if(S < 1)
{
P *= 1 - a[i];
S += a[i] / (1 - a[i]);
}
}
printf("%.10lf", P * S);
return 0;
}
Codeforces 442B. Andrey and Problem的更多相关文章
- Codeforces 442B Andrey and Problem(贪婪)
题目链接:Codeforces 442B Andrey and Problem 题目大意:Andrey有一个问题,想要朋友们为自己出一道题,如今他有n个朋友.每一个朋友想出题目的概率为pi,可是他能够 ...
- codeforces 442B B. Andrey and Problem(贪心)
题目链接: B. Andrey and Problem time limit per test 2 seconds memory limit per test 256 megabytes input ...
- codeforces#253 D - Andrey and Problem里的数学知识
这道题是这种,给主人公一堆事件的成功概率,他仅仅想恰好成功一件. 于是,问题来了,他要选择哪些事件去做,才干使他的想法实现的概率最大. 我的第一个想法是枚举,枚举的话我想到用dfs,但是认为太麻烦. ...
- Codeforces Round #253 (Div. 1) B. Andrey and Problem
B. Andrey and Problem time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- Codeforces 442B
题目链接 B. Andrey and Problem time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- [codeforces 528]B. Clique Problem
[codeforces 528]B. Clique Problem 试题描述 The clique problem is one of the most well-known NP-complete ...
- cf442B Andrey and Problem
B. Andrey and Problem time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- codeforces.com/contest/325/problem/B
http://codeforces.com/contest/325/problem/B B. Stadium and Games time limit per test 1 second memory ...
- CodeForces 867B Save the problem
B. Save the problem! http://codeforces.com/contest/867/problem/B time limit per test 2 seconds memor ...
随机推荐
- CF822F Madness
题意:给你一棵边权都为1的树,要求选择互不相交的若干条路径,这些路径包含有所有点. 在每一条路径上选择一条边,放置一个动点,设置一个方向,它开始在该路径上来回运动,速度为1.每个点上都有一个停表,当有 ...
- vs2013x64&&qt5.7.1编译osg3.4.0&&osgEarth2.7
此文仅备忘: 1.安装VS2013_Cn_Ult 2.安装qt-opensource-windows-x86-msvc2013_64-5.7.1 设置环境变量QTDIR,并将其bin加入到path中. ...
- PHP缓存技术的应用1
// 自定义缓存类 class Cache_Filesystem { // 缓存写保存 function set ($key, $data, $ttl) { //打开文件为读/写模式 $h = fop ...
- 0910CSP-S模拟测试赛后总结
%%%外校参加国赛大佬kai神-rank1 ---------------以上选手实力开挂---------------- %%%skyh.NC锅-rank2 %%%神牛170-rank4 %%%迪哥 ...
- C++和JavaScript脚本的相互调用
脚本调用C++相对比较容易,使用ATL组件只需要抛双接口即可,但在exe里如何做到呢?本文实现了在exe里脚本和C++的相互调用.在EXE里也需要对外抛送一个继承自IDispatch的接口.并需要重载 ...
- C# .net async await 学习
async/await简单介绍 在处理比较耗时的操作(如图片处理.数据压缩.http请求等)传统的异步方法是直接使用Thread或者Task进行操作,在复杂的应用编写中可能会出现回调的问题,因此C#目 ...
- Map和Reduce函数
- JS数组 一起组团(什么是数组)一个数组变量可以存放多个数据
一起组团(什么是数组) 我们知道变量用来存储数据,一个变量只能存储一个内容.假设你想存储10个人的姓名或者存储20个人的数学成绩,就需要10个或20个变量来存储,如果需要存储更多数据,那就会变的更麻烦 ...
- JS规则 我与你同在(逻辑与操作符)数学中的“b大于a,b小于c”是“a<b<c”,那么在JavaScript中可以用&&表示
我与你同在(逻辑与操作符) 数学里面的"a>b",在JavaScript中还表示为a>b:数学中的"b大于a,b小于c"是"a<b& ...
- spring:AOP面向切面编程(注解)03
使用注解写aop时最好使用环绕通知写 切面类: /** * 用于记录日志的工具类,它里面提供了公共的代码 */ @Component("logger") @Aspect //表示当 ...