Time Limit:2s Memory Limit:128MByte
Submissions:82Solved:45
You are given an expression: A0O1A1O2A2⋯OnAnA0O1A1O2A2⋯OnAn, where Ai(0≤i≤n)Ai(0≤i≤n) represents number, Oi(1≤i≤n)Oi(1≤i≤n) represents operator. There are three operators, &,|,^&,|,^, which means and,or,xorand,or,xor, and they have the same priority.
The ii-th operator OiOi and the numbers AiAi disappear with the probability of pipi.
Find the expected value of an expression.
题目大意:
有N+1个数Ai.有N个位运算操作,在其中间隔排列,当前位运算操作出现的概率是1-pi,问最终获得的值的期望。
思路:
按位dp.分成20位、设定Dp【i】【2】:
①Dp【i】【0】表示对应当前位,到了第i个操作符,运算结果为0的概率
②Dp【i】【1】表示对应当前位,到了第i个操作符,运算结果为1的概率
那么状态转移方程我们到当前位i分两种情况考虑即可:
①当前操作符不粗线了。
②当前操作符出现。
然后再分操作符的三种情况转移一下就行了。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
int a[15000];
int num[15000];
char op[15000][3];
double p[15000];
double dp[15000][3];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<=n;i++)scanf("%d",&num[i]);
for(int i=1;i<=n;i++)scanf("%s",op[i]);
for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
double output=0;
for(int i=0;i<=20;i++)
{
for(int j=0;j<=n;j++)
{
if((num[j]&(1<<i))>0)
{
a[j]=1;
}
else a[j]=0;
}
memset(dp,0,sizeof(dp));
dp[0][a[0]]=1;
for(int j=1;j<=n;j++)
{
dp[j][0]=dp[j-1][0]*p[j];
dp[j][1]=dp[j-1][1]*p[j];
if(op[j][0]=='|')
{
if(a[j]==0)
{
dp[j][0]+=dp[j-1][0]*(1-p[j]);
dp[j][1]+=dp[j-1][1]*(1-p[j]);
}
if(a[j]==1)
{
dp[j][1]+=dp[j-1][0]*(1-p[j]);
dp[j][1]+=dp[j-1][1]*(1-p[j]);
}
}
if(op[j][0]=='&')
{
if(a[j]==0)
{
dp[j][0]+=dp[j-1][0]*(1-p[j]);
dp[j][0]+=dp[j-1][1]*(1-p[j]);
}
if(a[j]==1)
{
dp[j][0]+=dp[j-1][0]*(1-p[j]);
dp[j][1]+=dp[j-1][1]*(1-p[j]);
}
}
if(op[j][0]=='^')
{
if(a[j]==0)
{
dp[j][0]+=dp[j-1][0]*(1-p[j]);
dp[j][1]+=dp[j-1][1]*(1-p[j]);
}
if(a[j]==1)
{
dp[j][0]+=dp[j-1][1]*(1-p[j]);
dp[j][1]+=dp[j-1][0]*(1-p[j]);
}
}
}
output+=(dp[n][1]*(1<<i));
}
printf("%.6f\n",output);
}
}