HDU 5985 概率

n种硬币各有cnt[i]枚,每轮下其有p[i]概率保留,问各种硬币只有它存活到最后一轮的概率。

设k轮后i硬币存活概率$a[i][k]=(1-p^k_i)^{cnt[i]}$

则最后只有第i种硬币存活概率为$sumlimits_{k=1}^{+infty}{sumlimits_{j=1,j!=i}^{cnt[i]}{((1-a[i][k])-(1-a[i][k+1])) imes a[j][k-1]}}$

设k为10000次足够了

/** @Date    : 2017-10-06 16:06:03
  * @FileName: HDU 5985 概率.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoungEarlf@gmail.com)
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

int cnt[15];
double p[15];
double a[15][100010];
double ans[15];
double fpow(double a, int n)
{
	double res = 1.0;
	while(n)
	{
		if(n & 1)
			res *= a;
		a *= a;
		n >>= 1;
	}
	return res;
}

int main()
{
	int T;
	cin >> T;
	while(T--)
	{
		MMF(a);
		MMF(ans);
		int n;
		scanf("%d", &n);
		for(int i = 0; i < n; i++)
			scanf("%d%lf", cnt + i, p + i);
		if(n == 1)
		{
			printf("1.000000
");
			continue;
		}
		for(int i = 0; i < n; i++)
		{
			double tp = p[i];
			for(int j = 1; j <= 10000; j++)
			{
				a[i][j] = fpow(1.0 - tp, cnt[i]);
				tp *= p[i];
			}
		}
		for(int i = 0; i < n; i++)
		{
			ans[i] = 0.0;
			for(int j = 1; j < 9999; j++)
			{
				double t = 1.00;
				for(int k = 0; k < n; k++)
				{
					if(k == i)
						continue;
					else t *= a[k][j];
				}
				ans[i] += t * ((1.0 - a[i][j]) - (1.0 - a[i][j + 1]));
				/*cout << ans[i] << " ";
				cout << t << " ";
				cout << ans[i] << endl;*/
			}
		}
		for(int i = 0; i < n; i++)
			printf("%.6lf%s", ans[i], i==n-1?"
":" ");
	}
    return 0;
}
原文地址:https://www.cnblogs.com/Yumesenya/p/7657872.html