您的位置:首页 > 运维架构

2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) D.Dinner Bet 概率DP+排列组合

2017-04-23 20:09 543 查看
[b]题目链接[/b]:点这里

[b]题意:[/b]

  1~N标号的球

  现在A有C个,B有C个

  每次可以随机得到D个不同的球(1~N);问你A或B中的C个球都出现一次的 期望次数

[b]题解:[/b]

  dp[i][j][k]表示 随机出现了i个仅仅属于A的球的个数,仅仅属于B的球的个数,同时属于A,B的球的个数

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 1e5+10, M = 1e3+20, mod = 1e9+7, inf = 2e9;

LL Con[51][51];
double dp[12][12][12];
int vis[12][12][12],cnt[10],n,d,C,id[100];
double dfs(int i,int j,int k) {
if(vis[i][j][k]) return dp[i][j][k];
double& ret = dp[i][j][k];
vis[i][j][k] = 1;
if(i + k >= C || j + k >= C) return ret = 0;
double tmp = 1;
double xx;
for(int a = 0; a + i <= cnt[1]; ++a) {
for(int b = 0; b + j <= cnt[2]; ++b) {
for(int c = 0; c + k <= cnt[3]; ++c) {
if(a+b+c > d) continue;
double p = 1.0*Con[cnt[1]-i][a] *
Con[cnt[2]-j][b] * Con[cnt[3]-k][c] *
Con[n-cnt[1]-cnt[2]-cnt[3]+i+j+k][d-a-b-c]/Con
[d]*1.0;
if(a+b+c==0) {
xx = p;
}
else
{
tmp += p*dfs(i+a,j+b,k+c);
}
}
}
}
ret = tmp/(1-xx);
return ret;
}
int main()
{
for(int i = 0; i <= 50; ++i) {
Con[i][0] = 1,Con[i][i] = 1;
for(int j = 1; j < i; ++j)
Con[i][j] = Con[i-1][j] + Con[i-1][j-1];
}
scanf("%d%d%d",&n,&d,&C);
for(int i = 0; i < 2; ++i) {
for(int j = 1; j <= C; ++j) {
int x;
scanf("%d",&x);
id[x] |= (1<<i);
}
}
for(int i = 1; i <= n; ++i) if(id[i]) cnt[id[i]]++;
printf("%.12f\n",dfs(0,0,0));
return 0;
}

/*
2 1 1
1 2

30 5 10
2 3 5 7 11 13 17 19 23 29
20 18 16 14 12 10 8 6 4 2
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐