省选专练之 [HNOI2015]亚瑟王

版权声明:LeoJAM Presents https://blog.csdn.net/fcb_x/article/details/81914255

一道典型的题很难读懂

读懂我也做不起的题

看了一下题解

大抵是照着打出来了

F(i,j)表示前i个卡片有严格j张生效的期望概率

转移是这样的

F_{i,j}+=F_{i-1,j-1}[1-(1-p_{i})^{r-j+1}]

F_{i,j}+=F_{i-1,j}(1-(1-p_{i})^{r-j})

这是啥子意思:由于一张牌只能用一次

一个轮中假设用了j-1张剩下的有r-j的次数会考虑第i张

则有选和不选两种转移

最后统计每种的概率是相同的

#include<bits/stdc++.h>
using namespace std;
double F[251][251];
double G[251];
double p[251];
double d[251];
int n,r;
double quick_pow(double x,int k){
	double ret=1.0;
	while(k){
		if(k%2==1){
			ret=ret*x;
		}
		k/=2;
		x=x*x;
	}
	return ret;
}
int main(){
//	freopen("P3239.in","r",stdin);
	int Cas;
	scanf("%d",&Cas);
	while(Cas--){
		memset(F,0,sizeof(F));
		memset(G,0,sizeof(G));
		scanf("%d%d",&n,&r);
		for(int i=1;i<=n;i++){
			scanf("%lf%lf",&p[i],&d[i]);
		}
		F[1][0]=quick_pow(1.0-p[1],r);
		F[1][1]=G[1]=1.0-quick_pow(1.0-p[1],r);
		for(int i=2;i<=n;i++){
			for(int j=0;j<=min(i,r);j++){
				if(j)F[i][j]+=F[i-1][j-1]*(1.0-quick_pow(1.0-p[i],r-j+1));
				if(i!=j)F[i][j]+=F[i-1][j]*quick_pow(1.0-p[i],r-j);
			}
		}
		for(int i=2;i<=n;i++){
			for(int j=0;j<=min(i-1,r);j++){
				G[i]+=F[i-1][j]*(1.0-quick_pow(1.0-p[i],r-j));
			}
		}
		double  ans=0;
		for(int i=1;i<=n;i++)ans+=d[i]*G[i];
		printf("%.10lf\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/fcb_x/article/details/81914255