P2114 [NOI2014]起床困难综合症(位运算性质)

. \color{Red}Ⅰ.首先介绍一下自己想的方法

由于位运算间每一位互不影响

o n e [ i ] i 1 , 0 1 那么我们直接计算one[i]表示第i位是1时,操作到最后是0还是1

z e r o [ i ] i 0 , 0 1 zero[i]表示第i位是0时,操作到最后是0还是1

, 计算完之后,可以这样来算最后的答案

ll ans=0,temp=m;
for(int i=31;i>=0;i--)
{
	if( zero[i] )	ans+=bit[i];//第i位初始只要是0就好了,何乐而不为呢
	else if( one[i]&&temp>=bit[i] )//第i位初始是1才行,那么当前还选的数不大于m就拿!!
	//为什么能到就拿?因为如果不拿,就算拿了前面的所有1,也不会比(1<<i)的贡献多
	{
		temp-=bit[i];
		ans+=bit[i];
	} 
}

当然如果没想到高位往低位贪心,可以用用搜索来解决

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
ll a[maxn],one[maxn],zero[maxn],n,m,s,bit[maxn];
string w;
int main()
{
	cin >> n >> m;
	bit[0]=one[0]=1;
	for(int i=1;i<=31;i++)
		bit[i]=bit[i-1]*(ll)2,one[i]=1;
	for(int i=1;i<=n;i++)
	{
		cin >> w >> s;
		for(int j=0;j<=31;j++)//拿s的第j位去和 
		{
			int ok=0;
			if( s&bit[j] )	ok=1;
			if( w[0]=='A' )	one[j]&=ok,zero[j]&=ok;
			else if( w[0]=='O' )	one[j]|=ok,zero[j]|=ok;
			else	one[j]^=ok,zero[j]^=ok;
		}
	}
	ll ans=0,temp=m;
	for(int i=31;i>=0;i--)
	{
		if( zero[i] )	ans+=bit[i];//初始只要是0就好了,何乐而不为呢
		else if( one[i]&&temp>=bit[i] )
		{
			temp-=bit[i];
			ans+=bit[i];
		} 
	}
	cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107505573
今日推荐