fzu 2103 Bin & Jing in wonderland(组合数学)

题目连接:fzu 2103 Bin & Jing in wonderland


题目大意:给出n,k和r,表示有n种礼物,可以抽取k次礼物,要挑选r个礼物送人。然后给出n种礼物被抽中的概率,以及想要送得礼物序号。注意,抽取礼物之后只能按照礼物的标号从大到小排序后选后r个送人。例如,想要送1,1,2这样的情况,可以抽取4次。那么就只有抽取3个1和1个2的情况才可以,否则抽取两个2的话排序后即为1,1,2,2,选取后三位为1,2,2.


解题思路:将礼物的标号分为三大类,1)目标礼物中标号最小的那一个,tmp。2)比tmp标号小的礼物。3)比tmp大的礼物并且是目标礼物。

这样就可以根据组合数组计算出第三类礼物的概率P。

第二类礼物可以近似看成一种礼物,将概率想加的到pi。

然后枚举第一类礼物可能出现的次数,计算概率和ans。

答案即为ans * P。


#include <stdio.h>
#include <string.h>
#include <math.h>

typedef long long ll;

const int N = 60;

int n, k, r, tmp, v[N];
double P, p[N], pi, C[N][N];

void init() {
	memset(C, 0, sizeof(C));
	for (int i = 0; i <= 52; i++) {
		C[0][i] = 1;
		for (int j = 1; j <= i; j++)
			C[j][i] = C[j - 1][i] * (i - j + 1) / j;
	}
}

void input() {
	P = 1; pi = 0;
	scanf("%d%d%d", &n, &k, &r);
	memset(v, 0, sizeof(v));
	memset(p, 0, sizeof(p));

	int a;
	for (int i = 1; i <= n; i++) scanf("%lf", &p[i]);
	for (int i = 1; i <= r; i++) {
		scanf("%d", &a); v[a]++;
	}

	for (int i = 1; i <= n; i++) if (v[i]) {
		tmp = i; break;
	}

	int t = k;
	for (int i = tmp + 1; i <= n; i++) if (v[i]) {
		P *= pow(p[i], v[i]) * C[v[i]][t];
		t -= v[i];
	}
	for (int i = 1; i < tmp; i++) pi += p[i];
}

double solve() {
	int top = k - r + v[tmp];
	double ans = 0;

	for (int i = v[tmp]; i <= top; i++)
		ans += pow(p[tmp], i) * C[i][top] * pow(pi, top - i);

	return P * ans;
}

int main () {
	init();
	int cas;
	scanf("%d", &cas);
	while (cas--) {
		input();
		printf("%.6lf\n", solve());
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值