所以NOI的题现在简单惹?
30分做法:枚举开始的权值,n²过掉。
100分做法:竟然是贪心qwq。因为我们的计算背景是二进制下,所以我们贪心地想让每一位都是1.我们现在需要解决的问题,就是找到一个开始的攻击值。所以我们可以按位检查一下当前位是否可以为1,能不能更新答案。
Code
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 typedef long long ll; 6 7 ll lmax(ll a,ll b) 8 { 9 if(b>a) return b; 10 else return a; 11 } 12 13 int n,m; 14 ll ans; 15 char opt[10]; 16 struct door{ 17 int op; 18 ll t; 19 }d[200000]; 20 21 ll work(ll x) 22 { 23 for(int i=1;i<=n;i++) 24 { 25 if(d[i].op==1) 26 x=x&d[i].t; 27 if(d[i].op==2) 28 x=x|d[i].t; 29 if(d[i].op==3) 30 x=x^d[i].t; 31 } 32 return x; 33 } 34 35 int main() 36 { 37 scanf("%d%d",&n,&m); 38 for(int i=1;i<=n;i++) 39 { 40 scanf("%s",opt+1); 41 scanf("%lld",&d[i].t); 42 if(opt[1]=='A') d[i].op=1; 43 else if(opt[1]=='O') d[i].op=2; 44 else if(opt[1]=='X') d[i].op=3; 45 } 46 /*for(int i=0;i<=m;i++) 47 ans=lmax(ans,work(i));*/ 48 for(int i=31;i>=0;i--) 49 { 50 if(ans+(1<<i)>m) continue; 51 if(work(ans)<work(ans+(1<<i))) 52 ans+=(1<<i); 53 } 54 printf("%lld",work(ans)); 55 return 0; 56 }