P2114 [NOI2014] 起床困难综合症

本题就是让我们选一个([0,m])之间的数字,让这个数字经过n次位运算后最大。

位运算的特点就是在二进制位表示下不进位,因此,对于我们选定的数字x,我们可以枚举它这个位是1还是0,每个位的运算是两两不影响的。因此我们可以贪心的从高位往低位枚举,来判断。

对于x的第i位,要选1还是选0可以这样判断
1.已经填好的数字加上这个位的值(1<<i)不超过m
2.让第i位为0,和为1分别去计算,来判断哪个更优。

my code:

#include<iostream>
#include<cstdio>
#define rep(i,j,k) for(register int i(j);i<=k;++i)
#define drp(i,j,k) for(register int i(j);i>=k;--i)
#define bug puts(~~~~~~~);
#define bugout(x) cout<<x<<endl;
using namespace std;
typedef long long lxl;
template<typename T>
inline T  max(T &a, T &b) {
	return a > b ? a : b;
}
template<typename T>
inline T  min(T &a, T &b) {
	return a < b ? a : b;
}
const int N=1e5+79;
int n, m;
#define int long long
char ch[N][5];
int a[N];


inline int calc(int bit,int x){
	rep(i,1,n){
		int t=(a[i]>>bit)&1;
		if(ch[i][0]=='A') x&=t;
		else if(ch[i][0]=='O') x|=t;
		else x^=t;
	}
	return x;
}

 main() {
	ios::sync_with_stdio(false);
	cin>>n>>m;
 	
    rep(i,1,n){
     	cin>>ch[i];
     	cin>>a[i];
	}
	int val(0),ans(0);
	drp(i,29,0){
		int r0=calc(i,0);
		int r1=calc(i,1);
		if(val+(1<<i)<=m&&r0<r1){
			val+=(1<<i);
			ans+=r1<<i;
		}
		else ans+=r0<<i;
	}
	cout<<ans<<'
';
	return 0;
}

本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15216428.html

原文地址:https://www.cnblogs.com/QQ2519/p/15216428.html