Description
Organizing a programming contest is not an easy job. To avoid making the problems too difficult, the organizer usually expect the contest result satisfy the following two terms:
1. All of the teams solve at least one problem.
2. The champion (One of those teams that solve the most problems) solves at least a certain number of problems.
Now the organizer has studied out the contest problems, and through the result of preliminary contest, the organizer can estimate the probability that a certain team can successfully solve a certain problem.
Given the number of contest problems M, the number of teams T, and the number of problems N that the organizer expect the champion solve at least. We also assume that team i solves problem j with the probability Pij (1 <= i <= T, 1<= j <= M). Well, can you calculate the probability that all of the teams solve at least one problem, and at the same time the champion team solves at least N problems?
1. All of the teams solve at least one problem.
2. The champion (One of those teams that solve the most problems) solves at least a certain number of problems.
Now the organizer has studied out the contest problems, and through the result of preliminary contest, the organizer can estimate the probability that a certain team can successfully solve a certain problem.
Given the number of contest problems M, the number of teams T, and the number of problems N that the organizer expect the champion solve at least. We also assume that team i solves problem j with the probability Pij (1 <= i <= T, 1<= j <= M). Well, can you calculate the probability that all of the teams solve at least one problem, and at the same time the champion team solves at least N problems?
题意:
一场ACM比赛中,有M道题,T只队伍,现在知道每只队伍对于每一题的AC概率,问全场每个队伍都A出至少一题且至少有一只队伍A了N道题的概率。
范围:
N,M<=30,T<=1000
解法:
画一个维恩图: 假设A表示每个队伍做出至少一题,B表示至少有一只队伍做出N题,那么我们要求解的就是P(A∩B),也就是图中的黄色部分。
但是直接求至少一个这样的概率是比较难求的,需要先求反,然后再根据容斥相减得到。
可以考虑先求解P(A∩~B)也就是红色部分,然后用P(A)-P(A∩~B)得到P(A∩B),其中因为每一个队伍是相互独立的,所以可以单独求,求解方法为dp,dp[I][J]表示前I道题做出J道的概率,转移很简单,略过(可以看代码),然后 连乘每一只队伍的Σdp[1..N-1]就是P(A∩~B),同理求得P(A),然后相减即可得到P(A∩B)
坑点:POJ加速读入会跪...POJ的G++不支持%lf输出,需要用%f...总之就是POJ的judge system 太老了,需要注意一下。
过
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdlib.h>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<bitset>
#pragma comment(linker, "/STACK:1024000000,1024000000")
template <class T>
bool scanff(T &ret){ //Faster Input
char c; int sgn; T bit=0.1;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
if(c==' '||c=='\n'){ ret*=sgn; return 1; }
while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
ret*=sgn;
return 1;
}
#define inf 1073741823
#define llinf 4611686018427387903LL
#define PI acos(-1.0)
#define lth (th<<1)
#define rth (th<<1|1)
#define rep(i,a,b) for(int i=int(a);i<=int(b);i++)
#define drep(i,a,b) for(int i=int(a);i>=int(b);i--)
#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)
#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)
#define mem(x,val) memset(x,val,sizeof(x))
#define mkp(a,b) make_pair(a,b)
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
double p[1001][33];
double dp[33][33];
int n,t,m;
int main(){
while(scanf("%d%d%d",&m,&t,&n)!=EOF){
if(m==0&&t==0&&n==0)break;
//POJ加速读入会跪...
rep(i,1,t)
rep(j,1,m)scanf("%lf",&p[i][j]);
double pa=1.0;
double pb=1.0;
rep(k,1,t){
dp[0][0]=1;
rep(i,1,m)
rep(j,0,i){
dp[i][j]=dp[i-1][j]*(1.0-p[k][i]);
if(j)dp[i][j]+=dp[i-1][j-1]*p[k][i];
}
double suma,sumb;
suma=sumb=0;
rep(i,1,n-1)sumb+=dp[m][i],suma+=dp[m][i];
rep(i,n,m)suma+=dp[m][i];
pa*=suma;
pb*=sumb;
}
//POJ的G++不支持%lf输出...
printf("%.3f\n",pa-pb);
}
}<strong>
</strong>