codeforces#253 D - Andrey and Problem里的数学知识

这道题是这样的,给主人公一堆事件的成功概率,他只想恰好成功一件。

于是,问题来了,他要选择哪些事件去做,才能使他的想法实现的概率最大。


我的第一个想法是枚举,枚举的话我想到用dfs,可是觉得太麻烦。

于是想是不是有什么规律,于是推导了一下,推了一个出来,写成代码提交之后发现是错的。

最后就没办法了,剩下的时间不够写dfs,于是就放弃了。


今天看thnkndblv的代码,代码很短,于是就想肯定是有什么数学规律,于是看了一下,

果然如此。


是这样的,还是枚举,当然是有技巧的,看我娓娓道来。


枚举的话,假设总共有n件事件,


从中选择1件事情去做,实现的概率最大是多少,


选择2件事情去做,实现的概率最大是多少,以此类推到选择n件事情去做。


于是就会得到n个结果,里面最大的那个就是实现主人公想法的最大概率。


这样的话要从n件事件中任意选出1件事情然后比概率,任意选出2件事情然后比概率……任意选出n件事情然后比概率


还是要搜索。


但是这里就有数学知识了,可以不用搜索,做法是这样的:


将n个事件成功的概率从大到小排序,

然后,

只选择前1件事去做成功的概率就是“从中选择1件事情去做,最大的实现概率”

只选择前2件事去做成功的概率就是“从中选择2件事情去做,最大的实现概率”

以此类推。


有了这个,这道题就很简单了,至于为什么这样做可以,无法证明,如果有人证明的话,欢迎留言讨论,附上原题以及地址和我后来AC的代码如下:

http://codeforces.com/contest/443/problem/D

D. 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.


#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(double a,double b)
{
	return a>b;
}
int main()
{
	int n,i,j,k;
	double a[110],x,sum,MAX;
	scanf("%d",&n);
	for(i=0;i<n;i++)
		scanf("%lf",&a[i]);
	sort(a,a+n,cmp);
	MAX=0;
	for(i=1;i<=n;i++)
	{
		sum=0;
		for(j=0;j<i;j++)
		{
			x=a[j];
			for(k=0;k<i;k++)
			{
				if(j!=k)
					x*=1-a[k];
			}
			sum+=x;
		}
		MAX=max(sum,MAX);
	}
	printf("%.12lf\n",MAX);
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值