Luogu 2114 [NOI2014]起床困难综合症

还挺简单的。

发现这几个二进制运算并不会进位,所以我们从高到低按位贪心,一位一位计算贡献。

发现$2^{30}$刚好大于$1e9$,所以最多只要算29位。

首先算出一个全都是$0$的二进制数和一个全都是$1$的二进制数通过所有的门之后每一位的情况,可以压成两个变量做。

最后贪心的时候先看看这一位取$0$能不能取到$1$,再看看这一位取$1$能不能取到$1$,如果可以就算上消耗$m$的代价取这个$1$。

因为高位取$1$一定比低位取$1$优,所以算出来的一定是最好答案。

一个每一位全都是$1$的二进制数可以通过机器补码的特性写成$-1$。

时间复杂度$O(nlogMaxInt)$。

Code:

#include <cstdio>
#include <cstring>
using namespace std;

int n, m, v1, v0;

int main() {
//    freopen("testdata.in", "r", stdin);
    
    scanf("%d%d", &n, &m);
    v0 = 0, v1 = -1;
    
    for(int i = 1; i <= n; i++) {
        char op[4]; scanf("%s", op);
        int now; scanf("%d", &now);
        if(op[0] == 'A') v1 &= now, v0 &= now;
        if(op[0] == 'O') v1 |= now, v0 |= now;
        if(op[0] == 'X') v1 ^= now, v0 ^= now;
    }
    
    int ans = 0;
    for(int i = 29; i >= 0; i--) {
        if((v0 >> i) & 1) ans += (1 << i);
        else if(((v1 >> i) & 1) && (1 << i) <= m) m -= (1 << i), ans += (1 << i); 
    }
    
    printf("%d\n", ans);
    return 0;
}
View Code

 

posted @ 2018-09-04 20:17  CzxingcHen  阅读(119)  评论(0编辑  收藏  举报