[P2114] [NOI2014]起床困难综合症 (位运算)
题面
传送门:https://www.luogu.org/problemnew/show/P2114
Solution
一道很有意思的位运算题.
要做这一题,我们首先得了解一个很重要的特点
位运算过程中每一位都不会进位
有了这个特点,我们可以考虑一个很妙的做法
我们可以把每一扇门的那个数转为2进制
就可以在O(n) 的时间内找到这一位以1或0为初始数,过完所有门后的这位数的结果
显然,结果为1是对答案有贡献的
然后,我们从后往前,一位一位枚举看一下初始值是填1还是填0
然后就OjbK了
时间复杂度O(logm*n)
Solution
//Luogu P2114 [NOI2014]起床困难综合症 //May,26th,2018 //位运算拆分法 #include<iostream> #include<cstdio> using namespace std; long long read() { long long x=0,f=1; char c=getchar(); while(!isdigit(c)){if(c=='-') f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0';c=getchar();} return x*f; } const int N=100000+1000; const int LEN=35; struct OP { int a[LEN],type; }op[N]; long long n,m; int Count(int x,int p) { for(int i=1;i<=n;i++) { if(op[i].type==1) x=x & op[i].a[p]; else if(op[i].type==2) x=x | op[i].a[p]; else x=x ^ op[i].a[p]; } return x; } int main() { n=read(),m=read(); char temp[5]; for(int i=1;i<=n;i++) { scanf("%s",temp+1); if(temp[1]=='A') op[i].type=1; else if(temp[1]=='O') op[i].type=2; else op[i].type=3; int t_num=read(); for(int j=0;t_num!=0;j++) { op[i].a[j]=t_num%2; t_num/=2; } } long long used=0,ans=0; for(int i=0;i<=30;i++) { int temp=Count(0,i); if(temp==1) { ans+=(1<<i); continue; } temp=Count(1,i); if(temp==1 and used+(1<<i) <=m) { ans+=(1<<i); used+=(1<<i); } } printf("%lld",ans); return 0; }
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。