题目链接:传送门
题意:
给定一个表达式中间n+1项,然后中间有n个运算符,每个运算符与其后面相邻的数字,不进行运算的概率为p,求这个表达式最后值得期望。
分析:
因为这个表达式的运算都是位运算,因此我们可以来考虑每一位为1的概率,然后总的期望就要加上这个概率乘上2^(i-1)。下面来分析每一种运算的概率的计算方法。
首先我们设经历了前k-1个运算第i位为1的概率为dp[k-1].那么为0的概率就是(1-dp[k-1])
1."^": 如果第k个数的第i为为1,那么 dp[k] = dp[k-1]*p + (1-dp[k-1])*(1-p),如果如果第k个数的第i为为0那么dp[k]=dp[k-1];
2."&": 如果第k个数的第i为为1,那么dp[k]=dp[k-1],如果第k个数的第i为为0,那么dp[k]=dp[k-1]*p;
3."|": 如果第k个数的第i为为1,dp[k]=dp[k-1]+(1-dp[k-1])*(1-p),如果第k个数的第i为为0,dp[k]=dp[k-1].
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
int a[500];
char s[500];
char ord[500];
double p[500];
int main()
{
int n,cas=1;
while(~scanf("%d",&n))
{
for(int i=0; i<=n; i++)
scanf("%d",a+i);
getchar();
gets(s);
for(int i=1; i<=n; i++)
scanf("%lf",p+i);
int len=strlen(s);
int cnt = 1;
for(int i=0; i<len; i++)
{
if(s[i]!=' ')
ord[cnt++]=s[i];
}
double ans = 0;
for(int i=0;i<21;i++){
double tmp = a[0]&(1<<i) ? 1 : 0;;
for(int j=1;j<=n;j++){
int tag = a[j]&(1<<i) ? 1 : 0;
if(ord[j]=='^'){
if(tag)
tmp = (1.0-tmp)*(1.0-p[j])+tmp*p[j];
}
if(ord[j]=='&'){
if(!tag){
tmp = tmp*p[j];
}
}
if(ord[j]=='|'){
if(tag)
tmp=tmp+(1.0-tmp)*(1-p[j]);
}
}
ans=ans+tmp*(1<<i);
}
printf("Case %d:\n%.6lf\n",cas++,ans);
}
return 0;
}