2024-12-12 16:29阅读: 13评论: 0推荐: 0

Acwing 998. 起床困难综合症 题解

Tag: 位运算,贪心

link

题目描述

21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳。作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争。通过研究相关文献,他找到了该病的发病原因:在深邃的太平洋海底中,出现了一条名为 drd 的巨龙,它掌握着睡眠之精髓,能随意延长大家的睡眠时间。正是由于 drd 的活动,起床困难综合症愈演愈烈,以惊人的速度在世界上传播。为了彻底消灭这种病,atm 决定前往海底,消灭这条恶龙。历经千辛万苦,atm 终于来到了 drd 所在的地方,准备与其展开艰苦卓绝的战斗。drd 有着十分特殊的技能,他的防御战线能够使用一定的运算来改变他受到的伤害。具体说来,drd 的防御战线由 n 扇防御门组成。每扇防御门包括一个运算 op 和一个参数 t,其中运算一定是 OR,XOR,AND 中的一种,参数则一定为非负整数。如果还未通过防御门时攻击力为 x,则其通过这扇防御门后攻击力将变为 x op t。最终 drd 受到的伤害为对方初始攻击力 x 依次经过所有 n 扇防御门后转变得到的攻击力。

由于 atm 水平有限,他的初始攻击力只能为 0m 之间的一个整数(即他的初始攻击力只能在 0,1,,m 中任选,但在通过防御门之后的攻击力不受 m 的限制)。为了节省体力,他希望通过选择合适的初始攻击力使得他的攻击能让 drd 受到最大的伤害,请你帮他计算一下,他的一次攻击最多能使 drd 受到多少伤害。

提示

对于所有数据,保证 2n1050m1090t109,且 op 一定为 AND,OR,XOR 中的一种。

思路

在二进制下,最后的答案的每一位上要么是 0 要么是 1

那么我们先设两个量,一个初始化每一位都是1,一个初始化每一位都是0,然后模拟着运算。运算到最后我们可以得到每一位上如果开始是1和如果开始是0的最后情况。

那贪心策略就是让答案出现的 1 越多越好。

  • 如果是从 0 最后变成了 1(即伤害变多),一定是需要选取的。

  • 如果是从 1 最后变成了 1 且填上这个位置不超过 m,也是需要选取的。

  • 如果这个位置最后变成了 0,那不如填 0 给后面腾多一点的空间。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,ans,sum;
string op;
int t;
bitset<41> zero,one;
signed main()
{
	cin>>n>>m;
	zero.reset();//每一位归为 0
	one.set();//每一位归为 1
	for(int i=1;i<=n;i++)
	{
		cin>>op>>t;
		if(op=="AND")
		{
			zero&=t;
			one&=t;
		}
		else if(op=="XOR")
		{
			zero^=t;
			one^=t;
		}
		else
		{
			zero|=t;
			one|=t;
		}
	}
	for(int i=30;i>=0;i--)
	{
		if(zero[i]==1) ans+=(1LL<<i);//如果是从 0 最后变成了 1(即伤害变多),一定是需要选取的
		else if(one[i]==1&&m>=(sum+(1LL<<i))) //如果是从 1 最后变成了 1 且填上这个位置不超过 m,也是需要选取的。
		{
			ans+=(1LL<<i);
			sum+=(1LL<<i);//记录是否超过 m
		}
	}
	cout<<ans<<"\n";
	return 0;
}

本文作者:yaaaaaan

本文链接:https://www.cnblogs.com/yaaaaaan/p/18602910

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   yaaaaaan  阅读(13)  评论(0编辑  收藏  举报
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑
点击右上角即可分享
微信分享提示