HDU 4649 Professor Tian(概率DP)题解

题意:一个表达式,n + 1个数,n个操作,每个操作Oi和数Ai+1对应,给出每个操作Oi和数Ai+1消失的概率,给出最后表达式值得期望。只有| , ^,&三个位操作

思路:显然位操作只对当前位相关,那么我们可以一位一位求解,算出每一位的概率,然后算出这一位所给出的贡献的期望。

代码:

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 200 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e4 + 7;
double dp[maxn][2], poss[maxn];
int a[maxn];
char op[maxn][2];
int main(){
    int n, ca = 1;
    while(~scanf("%d", &n)){
        for(int i = 0; i <= n; i++){
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; i++){
            scanf("%s", op[i]);
        }
        for(int i = 1; i <= n; i++){
            scanf("%lf", &poss[i]);
        }
        for(int i = 0; i < 20; i++){
            if(a[0] & (1 << i)){
                dp[i][1] = 1;
                dp[i][0] = 0;
            }
            else{
                dp[i][1] = 0;
                dp[i][0] = 1;
            }
        }
        double ans = 0;
        for(int k = 0; k < 20; k++){
            for(int i = 1; i <= n; i++){
                int bit = (1 << k) & a[i];
                double pre0 = dp[k][0], pre1 = dp[k][1];
                if(op[i][0] == '&'){
                    if(bit){
                        dp[k][1] = pre1;
                        dp[k][0] = pre0;
                    }
                    else{
                        dp[k][1] = pre1 * poss[i];
                        dp[k][0] = pre0 * (1 - poss[i]) + pre0 * poss[i] + pre1 * (1 - poss[i]);
                    }
                }
                else if(op[i][0] == '|'){
                    if(bit){
                        dp[k][1] = pre0 * (1 - poss[i]) + pre1;
                        dp[k][0] = pre0 * poss[i];
                    }
                    else{
                        dp[k][1] = pre1;
                        dp[k][0] = pre0;
                    }
                }
                else{   // ^
                    if(bit){
                        dp[k][1] = pre1 * poss[i] + pre0 * (1 - poss[i]);
                        dp[k][0] = pre0 * poss[i] + pre1 * (1 - poss[i]);
                    }
                    else{
                        dp[k][1] = pre1;
                        dp[k][0] = pre0;
                    }
                }
            }
//            printf("* %f %f\n", dp[k][0], dp[k][1]);
            ans += dp[k][1] * double(1 << k);
        }
        printf("Case %d:\n%.6f\n", ca++, ans);
    }
    return 0;
}

 

posted @ 2019-07-11 18:31  KirinSB  阅读(160)  评论(0编辑  收藏  举报