【BZOJ3668】[NOI2014] 起床困難綜合症(位運算思想)
阿新 • • 發佈:2018-11-22
大致題意: 給定一些位運算操作,讓你在\(0\sim m\)範圍內選一個初始值,使其在經過這些運算後得到的結果最大。
前置技能:關於位運算
作為一道位運算的題,如果你不知道什麼是位運算,那就完全做不了了。
關於位運算可以詳見這篇部落格:位運算相關(一)——位運算學習筆記。
接下來,我們還要了解位運算的一個性質:即位運算的各數位之間是互不影響的。
根據這個性質,我們就可以得出一個大致思路了。
大致思路
由於位運算時各數位是相互獨立的,因此對於各數位,其實只有兩種情況:\(0\)或\(1\)。
則我們可以考慮用兩個變數\(s1\)和\(s2\),初始化分別為\(0\)
則此時,對於二進位制下的某一位,有三種情況:
\(s1\)中這一位為\(1\)。說明如果這一位初始值為\(0\)時最終結果為\(1\),則自然選這一位為\(0\)。
- \(s1\)中這一位為\(0\),但\(s2\)中這一位為\(1\)。說明如果這一位初始值為\(1\)時最終結果為\(0\),則判斷當前這位是否能選為\(1\),如果能選,由於二進位制數的大小是由高位決定的,因此必選,否則為\(0\)。
\(s1\)和\(s2\)中這一位全為\(0\)。則說明這一位無論如何最終結果都為\(0\)
按照這樣的套路,就能求出答案了。
程式碼
#include<bits/stdc++.h> #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define Gmax(x,y) (x<(y)&&(x=(y))) #define Gmin(x,y) (x>(y)&&(x=(y))) #define abs(x) ((x)<0?-(x):(x)) #define swap(x,y) (x^=y^=x^=y) #define uint unsigned int #define LL long long #define ull unsigned long long #define INF 1000000000 using namespace std; int n,m,s1=0,s2=-1;//用兩個變數s1和s2分別表示每一位選0和選1的情況 class Class_FIO { private: #define Fsize 100000 #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++) #define pc(ch) (void)(FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch)) int f,FoutSize,Top;char ch,Fin[Fsize],*A,*B,Fout[Fsize],Stack[Fsize]; public: Class_FIO() {A=B=Fin;} inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));x*=f;} inline void reads(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())&&~ch);} inline void write(int x) {if(!x) return pc('0');x<0&&(pc('-'),x=-x);while(x) Stack[++Top]=x%10+48,x/=10;while(Top) pc(Stack[Top--]);} inline void clear() {fwrite(Fout,1,FoutSize,stdout),FoutSize=0;} }F; int main() { register int i,x,ans=0;register string op; for(F.read(n),F.read(m),i=1;i<=n;++i) { F.reads(op),F.read(x); switch(op[0]) { case 'A':s1&=x,s2&=x;break; case 'O':s1|=x,s2|=x;break; case 'X':s1^=x,s2^=x;break; } } for(i=30;~i;--i) if(s1&(1<<i)) ans+=1<<i;else if(s2&(1<<i)&&(1<<i)<=m) ans+=1<<i,m-=1<<i;//分類討論求答案 return F.write(ans),F.clear(),0; }