BZOJ 3668 NOI 2014 Day1_T1 起床困难综合症 二进制拆分
发布日期:2021-10-02 10:57:30 浏览次数:20 分类:技术文章

本文共 1328 字,大约阅读时间需要 4 分钟。

题目大意:给一些操作(只能是AND,OR,XOR),在极大值范围内选择一个数,使得这个数经过操作之后得到的值最大。

思路:很水,只要不O(n)的枚举,基本怎样都能过。

我的写法是先预处理题目给的操作,看每一位经过操作之后得到的数值,然后从最高位到最低位贪心的取值,在不超过极大值的情况下,尽量让当前位运算之后为1

一定要注意是从最高位到最低位,因为最高位取1一定比剩下位全取1还要优,这个题就水A了

CODE:

#include 
#include
#include
#include
using namespace std;struct Complex{ int opt; bool num[31]; int p; Complex() { p = 0; memset(num,false,sizeof(num)); }}ask[100100];
//注意范围,这里还WA了一次。。int cnt,_max;int temp[40];char s[10];bool ans[30];inline bool Check(bool flag,int pos);int main(){ cin >> cnt >> _max; for(int x,i = 1;i <= cnt; ++i) { scanf("%s%d",s,&x); if(s[0] == 'O') ask[i].opt = 1; if(s[0] == 'X') ask[i].opt = 2; if(s[0] == 'A') ask[i].opt = 3; while(x) { if(x&1) ask[i].num[ask[i].p] = true; x >>= 1; ask[i].p++; } } temp[0] = 1; for(int i = 1;i <= 30; ++i) temp[i] = temp[i - 1] << 1; int now = 0,k = 1,re = 0; for(int i = 30;i >= 0; --i) { if(Check(false,i)) re += temp[i]; else if(Check(true,i)) if(now + temp[i] <= _max) { now += temp[i]; re += temp[i]; } } cout << re; return 0;}inline bool Check(bool flag,int pos){ for(int i = 1;i <= cnt; ++i) { switch(ask[i].opt) { case 1:flag = flag | ask[i].num[pos]; break; case 2:flag = flag ^ ask[i].num[pos]; break; case 3:flag = flag & ask[i].num[pos]; break; } } return flag;}

转载地址:https://blog.csdn.net/jiangyuze831/article/details/39005957 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:BZOJ 3669 NOI 2014 魔法森林 最短路/LCT
下一篇:POJ 2488 A Knight's Journey 水搜索

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年03月28日 13时25分33秒