题目:
http://acm.hdu.edu.cn/showproblem.php?pid=4649
题意;
n+1个数, n个操作符, 每个操作符消失的概率为f,操作符消失时连同后面那个数消失.求出期望答案.
思路:
将每个数拆分成二进制位.
dp[i][j][0] :第i个数第j位取0的概率.
dp[i][j][1] :第i个数第j位取1的概率.
注意输出要 %.6f...
AC.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int num[205], a[205][25];
char c[205];
double f[205];
double dp[205][25][3];
int main()
{
//freopen("in", "r", stdin);
int n, ca = 1;
while(~scanf("%d", &n)) {
for(int i = 0; i <= n; ++i) {
scanf("%d", &num[i]);
}
for(int i = 1; i <= n; ++i) {
getchar();
scanf("%c", &c[i]);
}
for(int i = 1; i <= n; ++i) {
scanf("%lf", &f[i]);
}
memset(a, 0, sizeof(a));
for(int i = 0; i <= n; ++i) {
int k = 0;
while(num[i] > 0) {
a[i][k++] = num[i]%2;
num[i] = num[i]/2;
}
}
memset(dp, 0, sizeof(dp));
for(int i = 0; i < 21; ++i) {
if(a[0][i] == 1) {
dp[0][i][1] = 1;
}
else {
dp[0][i][0] = 1;
}
}
for(int i = 1; i <= n; ++i) {
for(int j = 0; j < 21; ++j) {
dp[i][j][0] = dp[i-1][j][0]*f[i];
dp[i][j][1] = dp[i-1][j][1]*f[i];
if(c[i] == '|') {
if(a[i][j] == 0) {
dp[i][j][0] += dp[i-1][j][0]*(1-f[i]);
dp[i][j][1] += dp[i-1][j][1]*(1-f[i]);
}
else if(a[i][j] == 1) {
dp[i][j][1] += dp[i-1][j][0]*(1-f[i]) + dp[i-1][j][1]*(1-f[i]);
}
}
if(c[i] == '^') {
if(a[i][j] == 0) {
dp[i][j][0] += dp[i-1][j][0]*(1-f[i]);
dp[i][j][1] += dp[i-1][j][1]*(1-f[i]);
}
else if(a[i][j] = 1) {
dp[i][j][0] += dp[i-1][j][1]*(1-f[i]);
dp[i][j][1] += dp[i-1][j][0]*(1-f[i]);
}
}
if(c[i] == '&') {
if(a[i][j] == 0) {
dp[i][j][0] += dp[i-1][j][0]*(1-f[i]) + dp[i-1][j][1]*(1-f[i]);
}
if(a[i][j] == 1) {
dp[i][j][0] += dp[i-1][j][0]*(1-f[i]);
dp[i][j][1] += dp[i-1][j][1]*(1-f[i]);
}
}
}
}
double t = 1, ans = 0;
for(int i = 0; i < 21; ++i) {
ans += dp[n][i][1] * t;
t *= 2;
}
printf("Case %d:\n", ca++);
printf("%.6lf\n", ans);
}
return 0;
}