http://acm.hdu.edu.cn/showproblem.php?pid=4649
Professor Tian
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 76 Accepted Submission(s): 48
As a result , Timer passed.
Now, you, the bad guy, also angered the Professor Tian when September Ends. You have to faced the problem too. The problem comes that there is an expression and you should calculate the excepted value of it. And the operators it may contains are '&' (and),'|'(or) and '^'(xor) which are all bit operators. For example: 7&3=3, 5&2=0, 2|5=7, 4|10=14, 6^5=3, 3^4=7.
Professor Tian declares that each operator O i with its coming number A i+1 may disappear, and the probability that it happens is P i (0<i<=n).
A i will be less than 2 20, 0<=P i<=1.
比较简单的一道DP问题,我们设dp[i][j]表示前i个数计算完之后第j位为1的概率(二进制),那最后的答案就是
dp[n][0]*2^0+dp[n][1]*2^1+dp[n][2]*2^2+......dp[n][20]*2^20.(这里的^为乘方运算)
对于dp[i][j],设第i个符号消失的概率为pi,第(i+1)个数的第j位为di,则分三种情况考虑:
1.第i个符号为&,这时若di为1,则dp[i][j]=dp[i-1][j],否则,dp[i][j]=pi*dp[i-1][j];
2.第i个符号为|,这时若di为1,则 dp[i][j]=pi*dp[i-1][j]+1-pi,否则,dp[i][j]=dp[i-1][j];
3.第i个符号位^,这时若di为1,则dp[i][j]=dp[i-1][j]*pi+(1-pi)*(1-dp[i-1][j]);,否则,dp[i][j]=dp[i-1][j];
最后统计答案即可。注意初始化,dp[0][j]=(a[0]>>j)&1(0<=j<=20)。代码如下:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
double dp[210][25];
char op[210];
double pi[210];
int a[210];
int main()
{
//freopen("dd.txt","r",stdin);
int n,i,j,T=0;
while(scanf("%d",&n)!=EOF)
{
printf("Case %d:\n",++T);
memset(dp,0,sizeof(dp));
for(i=0;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
cin>>op[i];
for(i=1;i<=n;i++)
scanf("%lf",&pi[i]);
for(i=0;i<=20;i++)
{
dp[0][i]=(double)((a[0]>>i)&1);
}
for(i=1;i<=n;i++)
{
for(j=0;j<=20;j++)
{
int tmp=(1&(a[i]>>j));
if(op[i]=='&')
{
if(tmp)
{
dp[i][j]=dp[i-1][j];
}
else
{
dp[i][j]=pi[i]*dp[i-1][j];
}
}
else if(op[i]=='|')
{
if(tmp)
{
dp[i][j]=pi[i]*dp[i-1][j]+1-pi[i];
}
else
{
dp[i][j]=dp[i-1][j];
}
}
else if(op[i]=='^')
{
if(tmp)
{
dp[i][j]=dp[i-1][j]*pi[i]+(1-pi[i])*(1-dp[i-1][j]);
}
else
{
dp[i][j]=dp[i-1][j];
}
}
}
}
double ans=0;
for(i=0;i<=20;i++)
{
ans+=(double)(1<<i)*dp[n][i];
}
printf("%.6lf\n",ans);
}
return 0;
}