2016Google校招笔试-Not So Random
题目描述
有一个随机数字生成函数,对于一个输入X,有A/100的概率生成 X AND K
,有B/100的概率生成 X OR K
,有C/100的概率生成 X XOR K
。 0 ≤ X, K ≤ 10^9,0 ≤ A, B, C ≤ 100,A+B+C = 100。 现在假设有N个这样的随机数字生成函数,问最后输出数字的期望值。
思路
对于数字二进制下的每一位只有两种状态0或者1,同时每一位相互独立,所以可以分开考虑每一位,就算出经过N步之后每一位为1的概率,则最后的期望可以表示为:$ expect = \sum_{j=0}^{31} {p_j * (1 « j)} $ ,$p_j$表示经过N步随机数字生成函数后第j位为1的概率。
所以,有DP:
令dp[i][j][s]表示经过i步随机数字生成函数后第j位状态为s的概率,s = 0 / 1,有状态转移方程:
If (k & (1 << j)) > 0 :
dp[i][j][0] += dp[i-1][j][0] * a / 100
dp[i][j][0] += dp[i-1][j][1] * c / 100
dp[i][j][1] += dp[i-1][j][1] * a / 100
dp[i][j][1] += dp[i-1][j][0] * b / 100
dp[i][j][1] += dp[i-1][j][1] * b / 100
dp[i][j][1] += dp[i-1][j][0] * c / 100
Else :
dp[i][j][0] += dp[i-1][j][0] * a / 100
dp[i][j][0] += dp[i-1][j][1] * a / 100
dp[i][j][0] += dp[i-1][j][0] * b / 100
dp[i][j][0] += dp[i-1][j][0] * c / 100
dp[i][j][1] += dp[i-1][j][1] * b / 100
dp[i][j][1] += dp[i-1][j][1] * c / 100
初始化,则根据X的每一位0或者1,对dp[0][j][0]和dp[0][j][1]赋值1或者0。
代码
#include <bits/stdc++.h> using namespace std; #define clr(x,c) memset(x, c, sizeof(x)) #define pb push_back #define mp make_pair #define pii pair<int, int> #define psi pair<string, int> #define inf 0x3f3f3f3f typedef long long lld; const int N = 111111; const int M = 31; // x & k >= 0, bit(31) = 0 double dp[N][M][2]; double solve() { double ret = 0.0; int n, x, k, a, b, c; cin >> n >> x >> k >> a >> b >> c; // init clr(dp, 0); for (int j = 0; j < M; ++j) { if ( x & (1 << j) ) { dp[0][j][0] = 0.0; dp[0][j][1] = 1.0; } else { dp[0][j][0] = 1.0; dp[0][j][1] = 0.0; } } // dp for (int j = 0; j < M; ++j) { for (int i = 1; i <= n; ++i) { if ( k & (1 << j) ) { dp[i][j][0] += dp[i-1][j][0] * a / 100; dp[i][j][0] += dp[i-1][j][1] * c / 100; dp[i][j][1] += dp[i-1][j][1] * a / 100; dp[i][j][1] += (dp[i-1][j][0] + dp[i-1][j][1]) * b / 100; dp[i][j][1] += dp[i-1][j][0] * c / 100; } else { dp[i][j][0] += (dp[i-1][j][0] + dp[i-1][j][1]) * a / 100; dp[i][j][0] += dp[i-1][j][0] * b / 100; dp[i][j][0] += dp[i-1][j][0] * c / 100; dp[i][j][1] += dp[i-1][j][1] * b / 100; dp[i][j][1] += dp[i-1][j][1] * c / 100; } } ret += dp[n][j][1] * (1 << j); } return ret; } int main () { freopen("F:/#test-data/in.txt", "r", stdin); freopen("F:/#test-data/out.txt", "w", stdout); ios::sync_with_stdio(false); cin.tie(0); cout << fixed << showpoint; int t; cin >> t; for (int cas = 1; cas <= t; ++cas) { cout << "Case #" << cas << ": "; cout << setprecision(9) << solve() << endl; } return 0; }
goudan-er SHARE · ALGORITHM
Algorithm