At first, I did not understand the meaning of the question. It was a tragedy. Then, after reading the question, I got the AC.
The meaning is to give N, then give N + 1 integers, and then give N operators (there are only three operations: Or, and, and | & ^) in this way, an expression can be obtained by inserting operators into integers in turn.
Then give N to the floating point number (0 ~ 1 represents probability) represents the loss probability of the operator and the integer on its right. For example, the following data set
1
1 2
&
0.5
An integer and an operator can form an expression 1 & 2, but for some reason, the expression operator and
There is a certain probability that the number will lose this set of data, that is, 0.5 of the probability that & 2 will be lost. The expected value of this expression is
When & 2 is not lost, 1 & 2 = 0.
When the expression is lost, it becomes 1. The expected value of this expression is 0*0.5 + 1*0.5 = 0.5;
No idea ....
The idea is as follows:
First decompress the state-convert the data into a 20-bit 01 for calculation. Because there are only 20 bits, and &, |, ^ will not carry, then one bit and one bit can see, each digit is not 0 or 1. In this way, the probability that each digit is 1 is obtained, multiplied by the decimal number of this digit, and accumulated, which gives rise to the overall expectation. For each bit, the state transition equation is as follows:
F [I] [j] indicates the number of I prior to this bit. The probability of j (0 or 1) is calculated.
F [I] [1] = f [I-1] [1] * p [I] + calculate the probability of 1 based on the values of different operators and I bits.
F [I] [0] is the same.
Initial status: f [0] [0 ~ 1] = 0 or 1 (set based on the first number)
F [n] [1]
The final result is to multiply the probability of each bitwise to the bitwise right of the given bitwise.
The following is my code:
# Include <cstdio> # include <bitset> # include <iostream> using namespace std; bitset <20> team [205]; // bitset is strongly recommended, this is fast and easy to use. The key is to save the space char ch [205]; int pow [20], n, cas = 0; double p [205], dp [20] [205] [2]; int cal (int I, char c, int j, int f = 0) // f = 0 indicates that the default value is the probability that the calculation is 0, f = 1 is the probability to be calculated as 1 {// The probability of this function calculation result can only be 1 or 0, so the true value int ans can be returned; if (c = '&') ans = I & j; if (c = '^') ans = I ^ j; if (c = '| ') ans = I | j; if (! F) return ans = 0; // return the probability that else return ans = 1 by calculating as 0; // return the probability that 1 is passed} int read () {if (! (Cin> n) return 0; // returns the false value for (int a, I = 0; I <= n; I ++) If no value is read) {cin> a; team [I] = a; // convert it to binary with bitset} for (int I = 0; I <n; I ++) cin> ch [I]; // read operator for (int I = 0; I <n; I ++) cin> p [I]; // read probability return 1;} void deal () {double ans = 0; for (int I = 0; I <20; I ++) // initialize the first probability if (team [0] [I]) dp [I] [0] [1] = 1, dp [I] [0] [0] = 0; else dp [I] [0] [1] = 0, dp [I] [0] [0] = 1; for (int I = 0; I <20; I ++) for (int j = 1; j <= n; j ++) {dp [I] [j] [1] = dp [I] [J-1] [1] * p [J-1] + (1-p [J-1]) * (dp [I] [J-1] [0] * cal (0, ch [J-1], team [j] [I], 1) + dp [I] [J-1] [1] * cal (1, ch [J-1], team [j] [I], 1 )); // if you do not understand the dp format, read the description at the end of the article .. // Calculate the probability of current 1 dp [I] [j] [0] = dp [I] [J-1] [0] * p [J-1] + (1-p [J-1]) * (dp [I] [J-1] [0] * cal (0, ch [J-1], team [j] [I]) + dp [I] [J-1] [1] * cal (1, ch [J-1], team [j] [I]); // calculate the probability of being 0 and the probability of being 1} for (int I = 0; I <20; I ++) ans + = pow [I] * dp [I] [n] [1]; // statistical result printf ("Case % d: \ n", ++ cas ); printf ("%. 6lf \ n ", ans);} int main () {for (int I = pow [0] = 1; I <20; I ++) pow [I] = pow [I-1] * 2; // calculate the bitwise of binary while (read () deal (); return 0 ;}
Dp [I] [j] [1] = dp [I] [J-1] [1] * p [J-1] + (1-p [J-1]) * (dp [I] [J-1] [0] * cal (0, ch [J-1], team [j] [I], 1) + dp [I] [J-1] [1] * cal (1, ch [J-1], team [j] [I], 1 ));
Dp [I] [j] [1] indicates the probability that the I-th bit becomes 1 after the first j operations, dp [I] [J-1] [1] * p [J-1], indicating the probability of making this 1 after the current operator and the number on its right disappears
(1-p [J-1]) * (dp [I] [J-1] [0] * cal (0, ch [J-1], team [j] [I], 1) + dp [I] [J-1] [1] * cal (1, ch [J-1], team [j] [I], 1 )); this entire string is the probability that the current operator and the number on its right do not disappear, so there is a common factor (1-p [J-1]) that represents the probability that the expression does not disappear, dp [I] [J-1] [0] * cal (0, ch [J-1], team [j] [I], 1) this statement calculates the probability of 1 if the current calculation result in the previous step is 0.
, Dp [I] [J-1] [0] This is the probability that the result is 0 calculated in the previous step, cal (0, ch [J-1], team [j] [I], 1) this is the probability to calculate 0 and the current operator and the number on the right to be 1. This probability is either one or zero, dp [I] [J-1] [1] * cal (1, ch [J-1], team [j] [I], 1) if the result of the previous operation is 1, then the probability of 1 is obtained after the current operation. Finally, this disgusting formula is completed... The formula 0 below can be understood accordingly, that is, dp [I] [j] [0] = dp [I] [J-1] [0] * p [J-1] + (1-p [J-1]) * (dp [I] [J-1] [0] * cal (0, ch [J-1], team [j] [I]) + dp [I] [J-1] [1] * cal (1, ch [J-1], team [j] [I]);
A code without comments is attached.
#include<cstdio>#include<bitset>#include<iostream>using namespace std;bitset<20> team[205];char ch[205];int pow[20],n,cas=0;double p[205];double dp[20][205][2];int cal(int i,char c,int j,int f=0){ int ans; if(c=='&') ans=i&j; if(c=='^') ans=i^j; if(c=='|') ans=i|j; if(!f) return ans==0; else return ans==1;}int read(){ if(!(cin>>n)) return 0; for(int a,i=0;i<=n;i++) { cin>>a; team[i]=a; } for(int i=0;i<n;i++) cin>>ch[i]; for(int i=0;i<n;i++) cin>>p[i]; return 1;}void deal(){ double ans=0; for(int i=0;i<20;i++) if(team[0][i]) dp[i][0][1]=1,dp[i][0][0]=0; else dp[i][0][1]=0,dp[i][0][0]=1; for(int i=0;i<20;i++) for(int j=1;j<=n;j++) { dp[i][j][1]=dp[i][j-1][1]*p[j-1]+(1-p[j-1])*(dp[i][j-1][0]*cal(0,ch[j-1],team[j][i],1)+dp[i][j-1][1]*cal(1,ch[j-1],team[j][i],1)); dp[i][j][0]=dp[i][j-1][0]*p[j-1]+(1-p[j-1])*(dp[i][j-1][0]*cal(0,ch[j-1],team[j][i])+dp[i][j-1][1]*cal(1,ch[j-1],team[j][i])); } for(int i=0;i<20;i++) ans+=pow[i]*dp[i][n][1]; printf("Case %d:\n",++cas); printf("%.6lf\n",ans);}int main(){ for(int i=pow[0]=1;i<20;i++) pow[i]=pow[i-1]*2; while(read()) deal(); return 0;}