这道题简单题意就是从0到m选一个数,进行n此操作,使得操作完的数最大。
这道题可以很暴力想到O(nm)的做法,枚举每个0到m的数进行n次操作后的值进行取最大值
但数据范围明显过不去,所以我们要优化一下
首先这些操作都是位运算,是在二进制下对每一位的操作。
因为二进制下每一位都相对独立,并且每一位只有0和1两种情况,所以我们从高位到低位枚举0或1(保证最优解最大),找出能得到最优解的x(0<=x<=m)
对于每一位枚举的0/1共有4种情况,
(ans为记录最优解大小,kkk记录x的大小)
当枚举为0时,
1.操作后为0时不用管它
2.操作后为1时ans累加
当枚举为1时
1.操作后为0时不管
2.操作后为1时且kkk加上这个二进制当前位的大小小于m时 kkk和ans累加。
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define ll long long using namespace std; const int maxn=1000000+101010; inline int read(){ int x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-'0'; return x*f; } int n,m; struct wzq{ int x,y; }a[maxn]; int main(){ n=read();m=read(); int kk=0,kkk=0; for(int i=1;i<=n;i++){ char b[30]; scanf("%s%d",b,&a[i].y); if(b[0]=='A')a[i].x=1; if(b[0]=='O')a[i].x=2; if(b[0]=='X')a[i].x=3; } for(int i=30;i>=0;i--){ int t=1<<i,k=0; for(int j=1;j<=n;j++){ if(a[j].x==1)t=t&a[j].y,k=k&a[j].y; if(a[j].x==2)t=t|a[j].y,k=k|a[j].y; if(a[j].x==3)t=t^a[j].y,k=k^a[j].y; } if(k&(1<<i))kk+=(1<<i); else if(t&(1<<i)){ if(kkk+(1<<i)>m)continue; kkk+=(1<<i); kk+=(1<<i); } } printf("%d",kk); return 0; } /* 10 AND 5 OR 6 XOR 7 */