【hdu 4696】Professor Tian

Link:http://acm.hdu.edu.cn/showproblem.php?pid=4649

Description

给你一个由位运算“与”“或”“和”组成的计算表达式;
每个运算符都有p[i]的几率消失;
问你最后这个计算表达式的值的期望是多少?
运算的数字< 220

Solution

因为二进制在进行位运算的时候,是不会产生进位的;
因此,我们可以一位一位地算;
即从二进制的第一位开始算,通过一个简单的DP,得到
这一位在n个数字做完之后为1的概率是多少;
然后乘上2^0即可;
对于第二位,第三位…用同样的方法做即可;
定义的状态为
f[i][j][k]表示第i位,在前j个数算完之后,为k的概率是多少,k=0或者1;

NumberOf WA

0

Reviw

二进制在计算的时候,不会产生进位->各个位的计算是独立的;
这里利用了一个独立的思想;

Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
using namespace std;

const int M = 20;
const int N = 200;

double f[M+10][N+10][2],p[N+10],ans = 0;
int two[M+10],n,a[N+10];
char s[N+10][5];

main(){
    //freopen("/home/ccy/rush.txt","r",stdin);
    two[0] = 1;
    for (int i = 1;i <= M;i++)
        two[i] = two[i-1]*2;
    int kk = 0;
    while(~scanf("%lld",&n)){
        ans = 0;
        for (int i = 1;i <= n+1;i++)
            scanf("%lld",&a[i]);
        for (int i = 1;i <= n;i++)
            scanf("%s",s[i]);
        for (int i = 1;i <= n;i++)
            scanf("%lf",&p[i]);
        for (int i = 0;i <= M-1;i++){
            int temp = two[i];
            if (a[1]&temp)
                f[i][1][1] = 1,f[i][1][0] = 0;
            else
                f[i][1][0] = 1,f[i][1][1] = 0;
            for (int j = 1;j <= n;j++){
                if (a[j+1]&temp){
                    if (s[j][0]=='&'){
                        f[i][j+1][1] = f[i][j][1];
                        f[i][j+1][0] = f[i][j][0];
                    }
                    if (s[j][0]=='|'){
                        f[i][j+1][1] = f[i][j][1] + f[i][j][0]*(1-p[j]);
                        f[i][j+1][0] = f[i][j][0]*p[j];
                    }
                    if (s[j][0]=='^'){
                        f[i][j+1][1] = f[i][j][0]*(1-p[j]) + f[i][j][1]*p[j];
                        f[i][j+1][0] = f[i][j][1]*(1-p[j]) + f[i][j][0]*p[j];
                    }
                }else{
                    //(a[j+1]&temp)==0
                    //a[j+1] in i  == 0
                    if (s[j][0]=='&'){
                        f[i][j+1][1] = f[i][j][1]*p[j];
                        f[i][j+1][0] = f[i][j][0] + f[i][j][1]*(1-p[j]);
                    }
                    if (s[j][0]=='|'){
                        f[i][j+1][1] = f[i][j][1];
                        f[i][j+1][0] = f[i][j][0];
                    }
                    if (s[j][0]=='^'){
                        f[i][j+1][1] = f[i][j][1];
                        f[i][j+1][0] = f[i][j][0];
                    }
                }
            }
            ans = ans + 1.0*temp*f[i][n+1][1];
        }
        printf("Case %lld:
%.6lf
",++kk,ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626152.html