HYSBZ 3668: [Noi2014]起床困难综合症

来源:互联网 发布:linux编辑器 编辑:程序博客网 时间:2024/05/01 21:28

题目分析

很明显,这道题不能直接枚举0~m左右数,很明显会超时,那么我们只能从高到低枚举每一位,最多有32位,每一位有2个状态(0,1),所以时间复杂度是64*10^5,注意如果这一位能取0达到1,那么必定取0,如果这一位取1则要判断是否超过m。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 100005;struct Node{    char op[5];    int t;}node[maxn];int main(){    int n,m;    while(scanf("%d%d", &n, &m) != EOF) {        for(int i = 0; i < n; i++)            scanf("%s %d", node[i].op, &node[i].t);        int temp = m, cnt = 0;        while(temp) { //计算位数            temp >>= 1;            cnt++;        }        int sum = 0,vis[50];        memset(vis, -1, sizeof(vis));        for(int i = cnt-1; i >= 0; i--){ //从最高位开始枚举,用贪心的思想            for(int k = 0; k <= 1; k++){                int x = k<<i;                for(int j = 0; j < n; j++){                    if(node[j].op[0] == 'A') x = x&node[j].t;                    else if(node[j].op[0] == 'O') x = x|node[j].t;                    else x = x^node[j].t;                }                if(((x>>i)&1) == 1 && vis[i] == -1) vis[i] = k;            }            if(vis[i] == 1 && (sum+(1<<i)) <= m) {                sum += 1<<i;            }        }        for(int j = 0; j < n; j++){            if(node[j].op[0] == 'A') sum = sum&node[j].t;            else if(node[j].op[0] == 'O') sum = sum|node[j].t;            else sum = sum^node[j].t;        }        printf("%d\n", sum);    }    return 0;}
0 0
原创粉丝点击