[NOI2014]起床困难综合症
这应该是$NOI2014$最简单的一题。
首先这题有$AND$、$OR$、$XOR$三个运算,跟二进制有关。
我们逐位看。
忽略$\leq m$的限制,在开始时每一位都可以是$0$或$1$,而不同的选择到最后的结果互不影响,所以共有四种组合。
想让结果更大,也就是想让结果尽可能多变成$1$。
加上$\leq m$的限制呢?
四种情况分别是:
(1)$0 \rightarrow 1 \ 1 \rightarrow 1$
(2)$0 \rightarrow 0 \ 1 \rightarrow 0$
(3)$0 \rightarrow 1 \ 1 \rightarrow 0$
(4)$0 \rightarrow 0 \ 1 \rightarrow 1$
前三种情况当然选择$0$,因为根据贪心即可保证结果最优,又可保证开始的数小。
第四种情况就要判断是否能选择$1$。如果选入了$1$使得开始的数$>m$,就不选。
正确性:从左往右,让结果为$1$,一定比从右往左选的结果更优,因为位数越靠左,数越大,优先选左边一定比右边要优。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b); 10 #define LL long long 11 #define inf (1 << 30) 12 13 inline int read() { 14 int w = 0, f = 1; char c = getchar(); 15 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 16 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 17 return w * f; 18 } 19 20 const int maxn = 1e5 + 5; 21 22 char opt[maxn][4]; 23 24 int bit[maxn][35], ans[maxn][2]; 25 int n, m; 26 27 int main() { 28 scanf("%d%d", &n, &m); 29 rep(i, 1, n) { 30 int v, L = 0; 31 scanf("%s %d", opt[i], &v); 32 while (v) { 33 bit[i][L++] = v & 1; 34 v >>= 1; 35 } 36 } 37 38 rep(i, 0, 30) { 39 rep(tag, 0, 1) { 40 int x = tag; 41 rep(j, 1, n) 42 if (opt[j][0] == 'A') x &= bit[j][i]; 43 else if (opt[j][0] == 'O') x |= bit[j][i]; 44 else x ^= bit[j][i]; 45 ans[i][tag] = x ? 1 : 0; 46 } 47 } 48 49 int res = 0, mx = 0; 50 repd(i, 30, 0) { 51 if (ans[i][0] == 0 && ans[i][1] == 1) 52 if (res + (1 << i) <= m) { 53 res += 1 << i; 54 mx += 1 << i; 55 } 56 if (ans[i][0] == 1 && ans[i][1] == 1 || ans[i][0] == 1 && ans[i][1] == 0) mx += 1 << i; 57 } 58 printf("%d", mx); 59 return 0; 60 }