题意:有$k$种苹果和$n$个箱子,每个箱子中有一些苹果,先等概率选取$n$个箱子组成集合的非空子集,再从选出的苹果中随机选一个,问每种苹果被选中的概率是多少

设箱子$i$有$cnt_{i,j}$个第$j$种苹果,第$i$个箱子的总苹果数$siz_i=\sum\limits_{j=1}^kcnt_{i,j}$,苹果总数$sum=\sum\limits_{i=1}^nsiz_i$

因为选完非空子集后,每个箱子中的苹果被选中的概率是相同的,所以先考虑选箱子,设$f_{i,j}$表示在前$i$个箱子中选$j$个苹果的方案数(只能一箱一箱选),那么$f_{i,j}=f_{i-1,j}+f_{i-1,j-siz_i}$

再设$g_{i,j}$表示在所有不是$i$的箱子中选$j$个苹果的方案数,那么$g_{i,j}=f_{n,j}-g_{i,j-siz_i}$

于是,选中了箱子$i$的情况对箱子$i$中每个苹果被选中的概率贡献为$\frac1{2^n-1}\sum\limits_{j=0}^{sum-siz_i}\frac{g_{i,j}}{j+siz_i}$(枚举箱子$i$外被选中的苹果数)

#include<stdio.h>
#include<vector>
#include<string>
#include<string.h>
using namespace std;
typedef double du;
typedef long long ll;
ll f[500010],g[500010];
int cnt[60][60],siz[60],sum;
class RandomApple{
	public:
		vector<du>theProbability(vector<string>hun,vector<string>ten,vector<string>one){
			int n,k,i,j;
			du t;
			n=hun.size();
			k=hun[0].length();
			for(i=0;i<n;i++){
				for(j=0;j<k;j++){
					cnt[i][j]=(hun[i][j]-'0')*100+(ten[i][j]-'0')*10+one[i][j]-'0';
					siz[i]+=cnt[i][j];
				}
				sum+=siz[i];
			}
			vector<du>res(k,0);
			f[0]=1;
			for(i=0;i<n;i++){
				for(j=sum;j>=siz[i];j--)f[j]+=f[j-siz[i]];
			}
			for(i=0;i<n;i++){
				memset(g,0,sizeof(g));
				t=0;
				for(j=0;j<=sum;j++){
					g[j]=f[j]-(j>=siz[i]?g[j-siz[i]]:0);
					if(j+siz[i]<=sum)t+=g[j]/(du)((1ll<<n)-1)/(du)(j+siz[i]);
				}
				for(j=0;j<k;j++)res[j]+=t*cnt[i][j];
			}
			return res;
		}
};
/*
int main(){
	RandomApple cl;
	vector<string>a,b,c;
	vector<du>res;
	char s[60];
	for(scanf("%s",s);s[0]!='-';scanf("%s",s))a.push_back(s);
	for(scanf("%s",s);s[0]!='-';scanf("%s",s))b.push_back(s);
	for(scanf("%s",s);s[0]!='-';scanf("%s",s))c.push_back(s);
	res=cl.theProbability(a,b,c);
	for(du t:res)printf("%.9lf ",t);
}
*/

[SRM478]RandomApple的更多相关文章

  1. SRM478

    又是rng_58的神题.. 250pt: 题意:给定一个初始数x,对于这个数可以进行x*4+3,或者x*8+7的操作.最多进行100000次操作 问最少经过几次出现%1000000007 == 0的情 ...

随机推荐

  1. bzoj 1406 数论

    首先问题的意思就是在找出n以内的所有x^2%n=1的数,那么我们可以得到(x+1)(x-1)=y*n,那么我们知道n|(x+1)(x-1),我们设n=a*b,那么我们对于任意的a,我们满足n%a==0 ...

  2. socket编程中write、read和send、recv之间的区别~转载

    socket编程中write.read和send.recv之间的区别   http://blog.csdn.net/petershina/article/details/7946615 一旦,我们建立 ...

  3. python实战===国内很简单实用的一些开源的api以及开源项目

    原创 2017年03月25日 15:40:59 标签: api / 开源项目 / app / 免费接口   声明 以下所有 API 均由产品公司自身提供,本人皆从网络获取.获取与共享之行为或有侵犯产品 ...

  4. python基础===抽象

    懒惰即美德 斐波那契数列: >>> fibs = [0,1] >>> for i in range(8): fibs.append(fibs[-2]+fibs[-1 ...

  5. C++内存管理(转)

    C++内存管理比较好的文章,参考链接如下: C++内存管理

  6. 【python】发送邮件

    从网上找了一些用python发邮件的教程,学习一下: 1.发送普通的文本邮件 http://www.cnblogs.com/xiaowuyi/archive/2012/03/17/2404015.ht ...

  7. 三:ZooKeeper的ZAB协议

    一:ZAB协议概述--->ZooKeeper并没有完全采用Paxos算法,而是使用了一种称为ZooKeeper Atomic Broadcast(ZAB,zookeeper原子消息广播协议)的协 ...

  8. numpy及scipy的使用

    numpy的使用 把list A转换为numpy 矩阵 np.array(A) np.array(A, 'int32') numpy加载txt文件里面的矩阵 matrix = np.loadtxt(t ...

  9. ibatis中的符号#跟$区别

    昨天一个项目中在写ibatis中的sql语句时,order by #field#, 运行时总是报错,后来上网查了查,才知道这里不该用#,而应该用$,随即查了下#与$的区别.  总结如下:  1.#是把 ...

  10. AIOps实践三板斧:从可视化、自动化到智能化

    http://ai.51cto.com/art/201806/576881.htm?mobile