又是两题的节奏
dp[i][j][2]表示第i个数的时候第j位为0或者1的期望
主要还是细心 对于每个操作进行判断
想到状态压缩这道题就不难了
#include <stdio.h>
#include <string.h>
#define MAXN 220
int num[MAXN];
char op[MAXN];
double p[MAXN];
int n;
int len(int n)
{
int cnt=0;
while(n>0)
{
cnt++;
n/=2;
}
return cnt;
}
double dp()
{
double dp[220][22][2];
memset(dp,0,sizeof(dp));
for(int i=0;i<=20;i++)
if(num[0]&(1<<i))
dp[0][i][1]=1;
else
dp[0][i][0]=1;
int max=len(num[0]);
for(int i=1;i<=n;i++)
{
max=max>len(num[i])?max:len(num[i]);
for(int j=20;j>=0;j--)
{
if(num[i]&(1<<j))
{
if(op[i]=='&')
{
dp[i][j][1]=dp[i-1][j][1];
dp[i][j][0]=dp[i-1][j][0];
}
if(op[i]=='|')
{
dp[i][j][1]=dp[i-1][j][1]+dp[i-1][j][0]*(1-p[i]);
dp[i][j][0]=dp[i-1][j][0]*p[i];
}
if(op[i]=='^')
{
dp[i][j][1]=dp[i-1][j][0]*(1-p[i])+dp[i-1][j][1]*p[i];
dp[i][j][0]=dp[i-1][j][0]*p[i]+dp[i-1][j][1]*(1-p[i]);
}
}
else
{
if(op[i]=='&')
{
dp[i][j][1]=dp[i-1][j][1]*p[i];
dp[i][j][0]=dp[i-1][j][0]+dp[i-1][j][1]*(1-p[i]);
}
if(op[i]=='|')
{
dp[i][j][1]=dp[i-1][j][1];
dp[i][j][0]=dp[i-1][j][0];
}
if(op[i]=='^')
{
dp[i][j][1]=dp[i-1][j][1];
dp[i][j][0]=dp[i-1][j][0];
}
}
}
}
double ans=0;
for(int i=0;i<=20;i++)
ans+=(1<<i)*dp[n][i][1];
return ans;
}
int main()
{
int ca=1;
while(scanf ("%d",&n)!=EOF)
{
for(int i=0;i<=n;i++)
scanf ("%d",&num[i]);
for(int i=1;i<=n;i++)
{
getchar ();
scanf ("%c",&op[i]);
}
for(int i=1;i<=n;i++)
scanf ("%lf",&p[i]);
double ans=dp();
printf("Case %d:\n%0.6lf\n",ca++,ans);
}
}