题意:有n个人准备去超市逛,其中第i个人买东西的频率是Pi。逛完以后得知有r个人买了东西,计算每个人实际买了东西的频率。输入n(1<=n<=20)和r(0<=r<=n),输出每个人实际买了东西的频率。
思路:“r个人买了东西”这个事件叫做E,“第i个人买东西”这个事件为Ei,要求P(Ei|E) = P(EiE) / P(E).条件概率公式
1.计算P(E).递归方式计算所有可能r个人买了东西的情况,比如n = 4,r = 2,有6种可能1100,1010,1001,0110,0101,0011,其中1100概率为P1 * P2 * (1 - P3) * (1 - P4),设置A[k]表示第k个人是否买东西(0表示没买,1表示买了),可以用递归的方法枚举恰好有r个A[k] = 1的情况
2.计算P(EiE),可以利用第一条时的递归,只不过要保证A[i] = 1
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define mod 1000000007;
using namespace std;
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
const int maxn = 20 + 2;
int n,r,A[maxn];
double tot,p[maxn],ans[maxn];
void dfs(int x,int sum)
{
if(sum == r)
{
double q = 1.0;
for(int i = 1;i <= n;i++)
{
if(A[i]) q *= p[i];
else q *= (1 - p[i]);
}
for(int i = 1;i <= n;i++) if(A[i]) ans[i] += q;
tot += q;
return;
}
for(int i = x;i <= n;i++)
{
// if(A[i]) continue;
A[i] = 1;
dfs(i + 1,sum + 1);
A[i] = 0;
}
}
int main()
{
int kase = 1;
while(scanf("%d%d",&n,&r) && n + r)
{
tot = 0;
memset(A,0,sizeof(A));
memset(ans,0,sizeof(ans));
for(int i = 1;i <= n;i++) scanf("%lf",&p[i]);
dfs(1,0);
printf("Case %d:\n",kase++);
for(int i = 1;i <= n;i++)
{
printf("%.6f\n",ans[i] / tot);
}
}
return 0;
}