题目链接
题意
某场比赛有M道问题,T支队伍,和数字N给出每支队伍解决每道问题的概率。 问这场比赛满足下面两个条件的概率
1.每支队伍至少做出一道题
2.冠军队至少做出N道题。
思路:下面转载别人博客中的解释,很详细,基本上看着这个思路,将之代码简化就能过,注意精度。
可以知道,每个人自己是互不影响的 对于一个选手 i 前 j 道题,做出 k 道题的概率F[i][j][k] = F[i][j - 1][k - 1] * p[i][j] + F[i][j - 1][k] * (1 - p[i][j])
那么问题可以转化为:所有至少做出一道的概率(p1) - 所有选手做出的题数n >= 1 && n < N 的概率(p2)
设s[i][j]表示F[i][M][0] + F[i][M][1] + … + F[i][M][j]
P1 = (s[1][M] - s[1][0])(s[2][M]-s[2][0])…*(s[T][M]-s[T][0])
P2 = (s[1][N-1] - s[1][0])(s[2][N-1]-s[2][0])…*(s[T][N-1]-s[T][0])
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
【代码】
#include<cstdio>
#include<cstring>
#include<iostream>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e3+10;
double p[N][N];
double dp[N][N];
double f[N][N];
int main()
{
int m,t,n;
while(~scanf("%d%d%d",&m,&t,&n)&&m&&t&&n)
{
double temp,p1=1;
rep(i,1,t)rep(j,1,m)scanf("%lf",&p[i][j]);
rep(i,1,t)
{
rep(j,1,m) rep(k,1,m) dp[i][j]=0;
//memset(dp,0,sizeof(dp));
dp[0][0]=1;
rep(j,1,m)
{
dp[j][0]=dp[j-1][0]*(1-p[i][j]);
rep(k,1,j) dp[j][k]=dp[j-1][k-1]*p[i][j]+dp[j-1][k]*(1-p[i][j]);
}
rep(k,1,m) f[i][k]=f[i][k-1]+dp[m][k];
}
double ans1=1,ans2=1;
for(int i=1;i<=t;++i)
{
ans1*=f[i][m];
ans2*=f[i][n-1];
}
printf("%.3f\n",ans1-ans2);
}
}