UOJ002 - Hard to Get Up
This problem is from NOI 2014.
Description
A warrior is to slay an evil dragon which hinders people from getting up easily. The dragon has gates defending it from attacks. On each gate there is an operation and a parameter . can be , or ,while is a non-negative integer.
The warrior needs to pass the gates one by one. If his attack power is before passing the gate, then his attack damage becomes after passing it. The damage taken by the dragon is the final result after all operations.
The warrior can freely choose his attack power from , which must be an integer. However, the intermediate results and the final damage can be larger than . Please help the warrior calculate the highest damage he can make if he chooses his attack power optimally.
Input
In the first line, there are two integers () and (), representing the number of gates and the upper bound of the warrior's attack power.
The following lines each contain a string and a non-negative integer () separated by a whitespace. is one of , or , and is the corresponding parameter.
Output
An integer, the highest damage the warrior can make.
Samples
Input 1
3 10
AND 5
OR 6
XOR 7
Output 1
1
Sample Explanation
If the warrior chooses as his initial attack power, then we have
So the final damage is .
Similarly, we can calculate that the final damage is if the initial attack power is and if the initial attack power is . So the highest damage the warrior can make is .
Tutorial
Hint 1
Consider each bit separately.
Hint 2
If for a set bit of , it is not worse to choose , we should choose . More than that, we are free to choose from and for the bits following.
Code (C++)
#include <bitset>
#include <iostream>
#include <vector>
using namespace std;
inline int go(int x, int y, int op_type) {
switch (op_type) {
case 0:
return x | y;
case 1:
return x & y;
default:
return x ^ y;
}
}
int main() {
int n, m;
cin >> n >> m;
vector<int> op(n);
vector<bitset<32>> t(n);
for (int i = 0; i < n; ++i) {
string s;
int ti;
cin >> s >> ti;
t[i] = bitset<32>(ti);
if (s == "AND")
op[i] = 1;
else if (s == "XOR")
op[i] = 2;
}
int ans = 0;
for (int i = 29; i >= 0; --i) {
bool flag = m & (1 << i);
int zero = 0, one = 1;
for (int j = 0; j < n; ++j) {
zero = go(zero, t[j][i], op[j]);
one = go(one, t[j][i], op[j]);
}
one = one && flag;
if (flag && (zero || !one))
m = (1 << i) - 1;
if (zero || one)
ans += 1 << i;
}
cout << ans;
}