题目链接:点这里
题意:
1~N标号的球
现在A有C个,B有C个
每次可以随机得到D个不同的球(1~N);问你A或B中的C个球都出现一次的 期望次数
题解:
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+, M = 1e3+, mod = 1e9+, inf = 2e9; LL Con[][];
double dp[][][];
int vis[][][],cnt[],n,d,C,id[];
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] = ;
if(i + k >= C || j + k >= C) return ret = ;
double tmp = ;
double xx;
for(int a = ; a + i <= cnt[]; ++a) {
for(int b = ; b + j <= cnt[]; ++b) {
for(int c = ; c + k <= cnt[]; ++c) {
if(a+b+c > d) continue;
double p = 1.0*Con[cnt[]-i][a] *
Con[cnt[]-j][b] * Con[cnt[]-k][c] *
Con[n-cnt[]-cnt[]-cnt[]+i+j+k][d-a-b-c]/Con[n][d]*1.0;
if(a+b+c==) {
xx = p;
}
else
{
tmp += p*dfs(i+a,j+b,k+c);
}
}
}
}
ret = tmp/(-xx);
return ret;
}
int main()
{
for(int i = ; i <= ; ++i) {
Con[i][] = ,Con[i][i] = ;
for(int j = ; j < i; ++j)
Con[i][j] = Con[i-][j] + Con[i-][j-];
}
scanf("%d%d%d",&n,&d,&C);
for(int i = ; i < ; ++i) {
for(int j = ; j <= C; ++j) {
int x;
scanf("%d",&x);
id[x] |= (<<i);
}
}
for(int i = ; i <= n; ++i) if(id[i]) cnt[id[i]]++;
printf("%.12f\n",dfs(,,));
return ;
} /*
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
*/