题目链接:
P2114 [NOI2014] 起床困难综合症 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目描述:
21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳。作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争。通过研究相关文献,他找到了该病的发病原因:在深邃的太平洋海底中,出现了一条名为 drd 的巨龙,它掌握着睡眠之精髓,能随意延长大家的睡眠时间。正是由于 drd 的活动,起床困难综合症愈演愈烈,以惊人的速度在世界上传播。为了彻底消灭这种病,atm 决定前往海底,消灭这条恶龙。历经千辛万苦,atm 终于来到了 drd 所在的地方,准备与其展开艰苦卓绝的战斗。drd 有着十分特殊的技能,他的防御战线能够使用一定的运算来改变他受到的伤害。具体说来,drd 的防御战线由 n 扇防御门组成。每扇防御门包括一个运算 op 和一个参数 t,其中运算一定是 OR,XOR,ANDOR,XOR,AND 中的一种,参数则一定为非负整数。如果还未通过防御门时攻击力为 x,则其通过这扇防御门后攻击力将变为x op t。最终 drd 受到的伤害为对方初始攻击力 x 依次经过所有 n 扇防御门后转变得到的攻击力。
由于 atm 水平有限,他的初始攻击力只能为 0 到 m 之间的一个整数(即他的初始攻击力只能在0,1,…,m 中任选,但在通过防御门之后的攻击力不受 m 的限制)。为了节省体力,他希望通过选择合适的初始攻击力使得他的攻击能让 drd 受到最大的伤害,请你帮他计算一下,他的一次攻击最多能使 drd 受到多少伤害。
输入格式:
输入文件的第 1 行包含 2 个整数,依次为 n,m,表示 drd 有 n 扇防御门,atm 的初始攻击力为 0 到 m 之间的整数。
接下来 n 行,依次表示每一扇防御门。每行包括一个字符串 op 和一个非负整数 t,两者由一个空格隔开,且 op 在前,t 在后,op 表示该防御门所对应的操作,t 表示对应的参数。
输出格式:
输出一行一个整数,表示 atm 的一次攻击最多使 drd 受到多少伤害。
输入输出样例:
输入
3 10 AND 5 OR 6 XOR 7
输出
1
说明/提示
【样例说明】
atm 可以选择的初始攻击力为 0,1,…,10。
假设初始攻击力为 4,最终攻击力经过了如下计算
4 AND 5=4
4 OR 6=6
6 XOR 7=1
类似的,我们可以计算出初始攻击力为 1,3,5,7,9 时最终攻击力为 0,初始攻击力为 0,2,4,6,8,10 时最终攻击力为 1,因此atm的一次攻击最多使drd受到的伤害值为 1。
【数据规模与约定】
思路:
由于n和m的范围太大,用暴力方法是行不通的,会TLE,这里我们采取贪心策略.
核心思路:用全0和全1的分别计算一遍,然后在不超过m的情况下,选在二进制下计算结果为1的那种情况
参考代码:
#include <bits/stdc++.h>
using namespace std;inline int read()
{bool sym = 0;int res = 0;char ch = getchar();while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();return sym ? -res : res;
}int main()
{int n = read(), m = read();int st1 = 0, st2 = pow(2, 31) - 1;string op;int t, ans = 0;while (n--){cin >> op;t = read();if (op == "AND")st1 &= t, st2 &= t;else if (op == "OR")st1 |= t, st2 |= t;else if (op == "XOR")st1 ^= t, st2 ^= t;}int tp = 0;for (int i = 30; i >= 0; i--){if (st1 >> i & 1)ans += (1 << i);else if (st2 >> i & 1 && tp + (1 << i) <= m)tp += (1 << i), ans += (1 << i);}printf("%d", ans);return 0;
}
#include <bits/stdc++.h>
using namespace std;typedef long long ll;
bitset<30> a, b(1073741823), c;
int r;
char s[5];inline int read()
{bool sym = 0;int res = 0;char ch = getchar();while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();return sym ? -res : res;
}int main()
{int n=read(),m=read();for (int i = 1; i <= n; i++){scanf("%s%d", s, &r);if (s[0] == 'A')a &= r, b &= r;if (s[0] == 'O')a |= r, b |= r;if (s[0] == 'X')a ^= r, b ^= r;}for (int i = 0; i < 30; i++)if (a[i] | (b[i] && c.to_ulong() < m))c[i] = 1;printf("%d", c.to_ulong());
}