每个队都至少 a c ac ac一题的概率减去每个队只 a c ac ac在 [ 1 , n − 1 ] [1,n-1] [1,n−1]的概率即可
首先可以预处理一个 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]数组
表示第 i i i个队伍前 j j j题 a c ac ac了 k k k题的概率
d p [ i ] [ j ] [ k ] = d p [ i ] [ j − 1 ] [ k − 1 ] ∗ p [ i ] [ j ] + d p [ i ] [ j − 1 ] [ k ] ∗ ( 1 − p [ i ] [ j ] ) dp[i][j][k]=dp[i][j-1][k-1]*p[i][j]+dp[i][j-1][k]*(1-p[i][j]) dp[i][j][k]=dp[i][j−1][k−1]∗p[i][j]+dp[i][j−1][k]∗(1−p[i][j])
然后就可以根据数组快速求了
#include <iostream>
#include <cstring>
using namespace std;
double dp[1009][41][41],p[1009][42];
int t,m,n;
int main()
{
while( cin >> m >> t >> n && (t+m+n) )
{
for(int i=1;i<=t;i++)
for(int j=1;j<=m;j++)
cin >> p[i][j];
memset(dp,0,sizeof(dp));
for(int i=1;i<=t;i++) dp[i][0][0]=1;
for(int i=1;i<=t;i++)
{
for(int j=1;j<=m;j++)
for(int q=0;q<=j;q++)//前j题作对q道
{
dp[i][j][q]=dp[i][j-1][q]*(1.0-p[i][j]);
if( q>=1 ) dp[i][j][q]+=dp[i][j-1][q-1]*p[i][j];
}
}
double ans=1,re=1;
for(int i=1;i<=t;i++)
{
double temp=0;
for(int j=1;j<=m;j++) temp+=dp[i][m][j];
ans*=temp;
temp=0;
for(int j=1;j<=n-1;j++) temp+=dp[i][m][j];
re*=temp;
}
printf("%.3f\n",ans-re);
}
}