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; }