zoukankan      html  css  js  c++  java
  • Luogu P2114 起床困难综合征

    Luogu P2114 起床困难综合征

    本题的关键之处在于,题目中给定的三种位运算——AND,OR,XOR,在二进制下皆是不进位的。这说明每一位都是独立的,启发我们可以按位考虑。
    因此我们从最高位向最低为依次考虑,每一位应该填$0$还是$1$。
    因为题目中 $m leq 10^9$ ,所以最多有 $30$ 位。( $10^9 < 2^{30}-1$ )
    对于第$k$位(最低位为第$0$位),改为应该填$1$,当且仅当满足下列两个条件:

    1. 已经填好的更高位构成的数值加上$2^k (1<<k)$之后不超过$m$;
    2. 用每个参数的第$k$位参与全部位运算。在所有位运算结束后保持不变。

    易知,对于条件2,如果不满足,则说明填$1$不如填$0$更优。
    在依次考虑完每一位后,就得到了答案。

    #include<bits/stdc++.h>
    #define N 100010
    
    using namespace std;
    
    int n,m,t,cnt,ans,tmp;
    char c[5];
    
    struct node {
    	int op,t;
    }a[N];
    
    void Read() {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) {
    		scanf("%s%d",c,&t);
    		if(c[0]=='A') {
    			a[++cnt].op=1;
    		}
    		else if(c[0]=='O') {
    			a[++cnt].op=2;
    		}
    		else if(c[0]=='X') {
    			a[++cnt].op=3;
    		}
    		a[cnt].t=t;
    	}
    	return;
    }
    
    int Calc(int bit,int val) {
    	int ret=val;
    	for(int i=1;i<=n;i++) {
    		int x=(a[i].t>>bit)&1;
    		if(a[i].op==1) {
    			ret&=x;
    		}
    		else if(a[i].op==2) {
    			ret|=x;
    		}
    		else if(a[i].op==3) {
    			ret^=x;
    		}
    	}
    	return ret;
    }
    
    void Solve() {
    	for(int i=29;i>=0;i--) {
    		int val0,val1;
    		val0=Calc(i,0);
    		val1=Calc(i,1);
    		if(tmp+(1<<i)<=m&&val0<val1) {
    			tmp+=(1<<i);
    			ans+=(val1<<i);
    		}
    		else {
    			ans+=(val0<<i);
    		}
    	}
    	printf("%d",ans);
    	return;
    }
    
    int main()
    {
    	Read();
    	Solve();
    	return 0;
    }
    
  • 相关阅读:
    偶遇this之坑
    程序员的职业素养——读后感
    我怎么没想到——读后感
    黑客与画家——读后感
    漫谈认证与授权
    动手造轮子:实现一个简单的依赖注入(二) --- 服务注册优化
    动手造轮子:实现简单的 EventQueue
    asp.net core 自定义 Policy 替换 AllowAnonymous 的行为
    SQL Server 中 `JSON_MODIFY` 的使用
    WeihanLi.Npoi 近期更新
  • 原文地址:https://www.cnblogs.com/luoshui-tianyi/p/11908944.html
Copyright © 2011-2022 走看看