【位运算】起床困难综合症(包含错误思路点拨)
原题
解题思路一(错误):
顺着做(每个数用数组存)的思路是人脑思路,但是电脑会TLE。我们可以反着来。
大概的思路就是先假设一个最终结果的最大值。
然后问电脑:这数运算回去(按照输入的门的顺序,逆着顺序运算回去)在我的m范围之内吗?
在,我就得寸进尺,我用11000000试(看是否 <= m);否则用01000000作为ans尝试。原则总是最高位优先,逐渐考虑低位。
错误原因:想当然。因为如a&b|c = d并不能得到 d|c&b = a,不能直接逆过去
解题思路二(超时):
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
struct data{int op,k;
}qry[N];
char s[10];
int n,m;
int suan(int a){for(int i=1;i<=n;i++){if(qry[i].op==1) a&=qry[i].k;if(qry[i].op==2) a|=qry[i].k;if(qry[i].op==3) a^=qry[i].k;}return a;
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s%d",s,&qry[i].k);if(s[0]=='A')qry[i].op=1;if(s[0]=='O')qry[i].op=2;if(s[0]=='X')qry[i].op=3;}int maxn=0;for(int i=0;i<=m;i++){ maxn = max(maxn,suan(i));}printf("%d\n",maxn);return 0;
}
思路就是遍历从0到m,每次取结果的最大值。但部分超时。
分析时间复杂度,n <= 1e5,m <= 1e9,相乘是1e14,超时是肯定的。所以我们要优化想法。
可以这样思考,比方说进门前的数字是1001?000,是10011000出门后比10010000出门后结果要大,那么10010000粗体0的低3位000无需考虑了!这是一个很关键的想法,因为位运算的每一位都是独立的。10011000的出门结果比10010000大,则表明从右往左第4位应该选用1而不是0,这样出门的结果对应的这一位也就是1.
那么,纵然第3位,10010000的输出是111,也不如10011000的出门结果大了。这是一种贪心的想法,因为只要高位比较大,无论低位如何,肯定是高位大的那个数结果大。这样就引入了下面的想法:
解题思路三(正确):
要尽量保持经过每个门运算之后,得到的结果最大。我们可以对通过门前的数进行逐位调整:在<m的前提下,如果某位是1使通过门后结果更大,那么就让这一位是1;否则不变(默认是0).
这样对最多31位进行考虑,运算的数量级和门的数量差一个常数,即1e5,不会超时。
//AC代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
struct data{int op,k;
}qry[N];
char s[10];
int n,m;
int cal(int a){for(int i=1;i<=n;i++){if(qry[i].op==1) a&=qry[i].k;if(qry[i].op==2) a|=qry[i].k;if(qry[i].op==3) a^=qry[i].k;}return a;
}
int main(){scanf("%d%d",&n,&m);for(int i = 1;i <= n;i++){scanf("%s%d",s,&qry[i].k);if(s[0]=='A') qry[i].op = 1;if(s[0]=='O') qry[i].op = 2;if(s[0]=='X') qry[i].op = 3;}int ans = 0;for(int i = 30;i >= 0;i--){ if(ans + (1 << i) > m) continue;if(cal(ans) < cal(ans + (1 << i))) ans += 1<<i;//如果入门前的数第i位是1时结果更大,则入门时的该位设置为1;否则不变 }printf("%d\n",cal(ans));return 0;
}
问:能否将① for(int i = 30;i >= 0;i--){
if(ans + (1 << i) > m) continue;
if(cal(ans) < cal(ans + (1 << i))) ans += 1<<i;
}
改成
② for(int i = 0;i <= 30;i++){
if(ans + (1 << i) > m) continue;
if(cal(ans) < cal(ans + (1 << i))) ans += 1<<i;
}
也就是说从最低位开始找使此位的最大输出的入门值?
答:不能!比方说可能最低位是1时得到该位的最大输出了,同时最高位是1也是最高位的最大输出。而这样组合得到的数超过了m的范围,就不符合题意,continue掉了。那么得到的答案就是一个较小的答案,这样得到的最终输出结果,是小于100000作为入门值的最终输出。
因为:最终输出的结果,高位大的则整个数大。所以我们很自然地要优先满足高位输出最大的要求。
比方说这样一个例子:
输入流为:
1 4
AND 5
Span | Doors | Op |
000 | 1 | &101 |
001 | ||
010 | ||
011 | ||
100 |
在①写法得到的结果是4;而在②写法得到的结果是1.
原因已经解释完毕。
【位运算】起床困难综合症(包含错误思路点拨)相关推荐
- 位运算 起床困难综合症
题目描述 21世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm一直坚持与起床困难综合症作斗争.通过研究相关文献,他找到了该病的发病原因 ...
- 位运算——起床困难综合症
传送门:998. 起床困难综合症 - AcWing题库 思路:因为每一位的操作都是互相独立的,所以从高位到低位枚举范围内的每一位,分别求取0或1的情况的最终答案,该位取1的情况下要保证和已经求出来的前 ...
- 起床困难综合症(0x01位运算)
起床困难综合症 题意 drd 的防御战线由 n 扇防御门组成. 每扇防御门包括一个运算 op 和一个参数 t,其中运算一定是 OR,XOR,AND 中的一种,参数则一定为非负整数. 如果还未通过防御门 ...
- CH0104 起床困难综合症(位运算典例)
传送门:起床困难综合症 思路:要知道位运算永远只会改变本位,与其它位泾渭分明.据此,我们不难看出,每个位仅有1.0两种状态,在全部运算后,寻找两种状态的最大结果即可. #include<cstr ...
- 起床困难综合症(位运算)
题目链接 AcWing 998. 题意:最初攻击力不知道,给定m次位运算操作,计算经过m次位运算操作后的最大值. 思路:在代码顶部 混合位运算不具有分配律,交换律,结合律 // 存在多个不同的位运算符 ...
- # 起床困难综合症(二进制枚举+按位求贡献)
起床困难综合症(二进制枚举+按位求贡献) 题意:n扇门,每扇门包括一个运算op和数x,玩家有一个初始攻击力[0,m],经过n扇门后的值为最终伤害值.给出n和m,求最大伤害值. code: #inclu ...
- BZOJ 3668: [Noi2014]起床困难综合症( 贪心 )
之前以为xor,or,and满足结合律...然后连样例都过不了 早上上体育课的时候突然想出来了...直接处理每一位是1,0的最后结果, 然后从高位到低位贪心就可以了... 滚去吃饭了.. ------ ...
- [BZOJ3668][Noi2014]起床困难综合症 贪心
3668: [Noi2014]起床困难综合症 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 2409 Solved: 1360 [Submit][ ...
- 洛谷 P2114 [NOI2014]起床困难综合症 解题报告
P2114 [NOI2014]起床困难综合症 题目描述 21世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm一直坚持与起床困难综合症作 ...
最新文章
- cass道路道路设计参数文件命令为什么没反应_为什么MySQL不建议使用delete删除数据?...
- 公司应该如果管理员工?
- 地域跨度入手的8zsb
- 编程实现 有符号乘法溢出判断
- Qtum研究院:市面上企业级解决方案都有哪些亮点?
- qtreewidgetitem 选中背景颜色_列表式报表阶梯背景色效果
- 45. 圆圈中最后剩下的数字
- 《别闹了,费曼先生》读书笔记
- 2018华为网络技术大赛
- iOS之性能优化·内置图片瘦身
- 3d胆码计算机方法,3D百十个位定胆技巧准确率95
- 《蔡康永说话之道》书摘
- 穷不坑朋友,富不忘恩人!
- 选择时间检定仪应该注意这11点
- 2020年10月份电脑选购计划
- eNSP 路由器配置-静态路由和缺省路由
- 一名IT界“老”技术人关于学习与成长的分享,受益!
- ImageFeatures
- 改做人工智能之前,90%的人都没能给自己定位
- 2019阿里技术电子书合集,打包下载