HDU5985 Lucky Conins 概率題

Lucky Conins

題意

最多共1010種硬幣,所有的硬幣之和不超過100000100000,每次將所有的硬幣拋出,第ii中硬幣正面朝上的概率爲pip_i,將反面朝上的硬幣移除掉.直至最後剩一種硬幣或沒有硬幣則停止.若最後剩餘一種硬幣,則稱這種硬幣是幸運的,求每種硬幣的幸運概率.

題解

推公式題.

假設我們要求第ii種硬幣成爲幸運硬幣的概率,那麼我們可以求其在第xx步成爲幸運硬幣的概率,然後對xx求和即可.

計算硬幣iixx步成爲幸運硬幣的概率:

一.第ii種硬幣,必須在第xx步至少剩11個:

[1] : Alive[i,x]=1(1pix)ciAlive[i,x] = 1-(1-p_i^x)^{c_i}

硬幣ii在第xx步存活:pixp_i^x,在第xx步及之前死亡:1pix1-p_i^x,第ii種所有硬幣在第xx步都死亡(1pix)ci(1-p_i^x)^{c_i},第ii種在第xx步至少剩餘一個硬幣1(1pix)ci1-(1-p_i^x)^{c_i}

二. 第jj種硬幣,至少有一枚要在第x1x-1步存活,第xx步死亡

先考慮對於第jj種硬幣,它至少有一枚硬幣第x1x-1步存活,在第xx步死亡的概率.

假設第jj種有tt枚硬幣在第x1x-1步存活,在第xx步死亡:

Ccjt(pjx1)t(1pjx1)cjt(1pj)t=Ccjt(pjx1pjx)t(1pjx1)cjtC_{c_j}^t(p_j^{x-1})^t(1-p_j^{x-1})^{c_j-t}(1-p_j)^t = C_{c_j}^t(p_j^{x-1}-p_j^{x})^t(1-p_j^{x-1})^{c_j-t}

tt11cjc_j求和,利用二項式定理我們得到了第jj種硬幣,它至少有一枚硬幣第x1x-1步存活,在第xx步死亡的概率:

[2] : (1pjx)cj(1pjx1)cj(1-p_j^{x})^{c_j}-(1-p_j^{x-1})^{c_j}.

三.除第ii種之外的所有硬幣,至少有11枚在x1x-1步存活,在第xx步死亡

爲避免重複計算

jj是不與ii相等的數中最小的.
我們考慮是第jj種硬幣起到了這個作用,那麼jj種以後的硬幣只要滿足在xx步及之前死光即可.

然後再考慮是j+tj+t種硬幣起到了這個作用,那麼j+tj+t種以後的硬幣只要滿足在xx步及之前死光即可,並且要滿足第j+tj+t種之前的硬幣必須不能起作用(即在x1x-1步及之前就必須全部死光),否則會算重.

也就是說我們需要記錄lft[j,x]lft[j,x]表示jj種之前的硬幣全部在第x1x-1步及之前就死光.記錄rgt[j,x]rgt[j,x]表示jj種之後的硬幣全都在第xx步及之前就死光.
其中lft[j,x]=ti,t<j(1ptx1)ctlft[j,x] = \sum_{t \ne i,t < j}(1-p_t^{x-1})^{c_t},rgt[j,x]=ti,t>jn(1ptx)ctrgt[j,x] = \sum_{t\ne i,t > j}^n(1-p_t^x)^{c_t}
那麼這部分的答案就是

ji((1pjx+1)cj(1pjx)cj)lft[j,x]rgt[j,x]\sum_{j \ne i}((1-p_j^{x+1})^{c_j}-(1-p_j^x)^{c_j})*lft[j,x]*rgt[j,x]

四.最終公式

(1(1pix)ci)ji(((1pjx)cj(1pjx1)cj)lft[j,x]rgt[j,x])(1-(1-p_i^x)^{c_i})\sum_{j \ne i}(((1-p_j^{x})^{c_j}-(1-p_j^{x-1})^{c_j})*lft[j,x]*rgt[j,x])

代碼

#include <iostream>
#include <algorithm>
#include <cstring>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)

double p[11];
int cnt[11];
int n;
const int lim = 50;
double fastpow(double x,int n) {
	double res = 1.0;
	while(n) {
		if(n&1) res *= x;
		x *= x;
		n >>= 1;	
	}
	return res;
}	

double f(int id,int x) {
	return fastpow(1-fastpow(p[id],x),cnt[id]) - fastpow(1-fastpow(p[id],x-1),cnt[id]);
}

double calc(int i) {
	double ans = 0;
	rep(x,1,lim) {
		double res = 1-fastpow(1-fastpow(p[i],x),cnt[i]);
		double tmp = 0,lft = 1;
		rep(j,1,n) {
			if(j == i) continue;
			double rgt = 1;
			rep(t,j+1,n) {
				if(i == t) continue;
				rgt *= fastpow(1-fastpow(p[t],x),cnt[t]);
			}
			tmp += f(j,x)*lft*rgt;
			lft *= fastpow(1-fastpow(p[j],x-1),cnt[j]);
		}
		ans += res * tmp;
	}
	return ans;
}
int main() {
	int T;
	std::cin >> T;
	while(T--) {
		std::cin >> n;
		rep(i,1,n) {
			std::cin >>	cnt[i] >> p[i];
		}
		if(n == 1) {
			printf("%.6f\n",1.0);
			continue;
		}
		rep(i,1,n) {
			if(i != 1) printf(" ");
			printf("%.6f",calc(i));
		}
		puts("");
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章