题目
题解
题意简化为:在0~m之间找一个数,使得这个数在一系列操作后最大。
由于原数有大小限制,又要使得到的数尽量大,为了充分地利用限制,就需要按位从高到低贪心,确定原数是选0还是选1。如果可以使得到的数为1,则尽量选,同时要考虑原数限制,还要使原数尽量小。
需要记录每一位为0或1时,在经过操作后会变成什么。只要用一个全0数和一个全1数整体操作即可,最后一位位取出来。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,a0,a1,t,ans,st;
char ch[5];
inline void get_ans()
{
for(int i=30;i>=1;i--) //st是原数
{
int cur=1<<(i-1); //cur只有第i位为1
if(a0&cur) ans+=cur; //优先考虑原数为0
else if(a1&cur&&st+cur<=m) ans+=cur,st+=cur;
} //若得到的数必为0,则原数默认为0
}
int main()
{
scanf("%d%d",&n,&m);
a0=0; a1=(1<<30)-1;
for(int i=1;i<=n;i++)
{
scanf("%s%d",ch,&t);
if(ch[0]=='A') a0&=t,a1&=t;
else if(ch[0]=='O') a0|=t,a1|=t;
else a0^=t,a1^=t;
}
get_ans();
printf("%d\n",ans);
return 0;
}
本文详细解析洛谷P2114[NOI2014]起床困难综合症的算法题解。通过贪心策略,从高位到低位确定原数的每一位,以最大化操作后的数值,同时考虑到原数的大小限制。

155

被折叠的 条评论
为什么被折叠?



