P2114 [NOI2014] 起床困难综合症(贪心+位运算)
题目大意:
要求在0--m之间的数,经过n次位运算后,最大是多少?
题解:
位运算的特点是,每一位是独立的,不存在进位和借位。
假设x∈[0,m],经过位运算后得到的结果最大,为z
位运算的特点 各个位互不影响
先用各位都为0和各位都为1的数经过所有的位运算
接下来我们来构造出x
对于 1000 > 0111,所以我们使z的高位尽可能有1
经过位运算出现1的情况有
(1)当该位为0,经过一系列位运算变为1,最优
(2)当该位为1,经过一系列位运算变为1,
当将该位变为1时,仍小于m,则将该位变为1.
m<=10^9<2^30
代码
#include<bits/stdc++.h> using namespace std; int n,m; int a0,a1; long long ans; int main() { cin>>n>>m; a0=0;a1=(1<<30)-1; for(int i=1;i<=n;i++) { string s; int x; cin>>s>>x; if(s[0]=='X') a0^=x,a1^=x; if(s[0]=='A') a0&=x,a1&=x; if(s[0]=='O') a0|=x,a1|=x; } for(int i=29;i>=0;i--) { if(a0&(1<<i)) ans|=(1<<i); else if((a1&(1<<i))&&(m>=(1<<i))) { ans|=(1<<i); m=m-(1<<i); } } cout<<ans; return 0; }