zoukankan      html  css  js  c++  java
  • 洛谷2114 bzoj3668[NOI2014]起床困难综合症

    题目描述

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

    输入输出样例

    输入样例#1: 
    3 10
    AND 5
    OR 6
    XOR 7
    输出样例#1: 
    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。

    一句话题意

    找一个小于M 的数 使它经过N次给定的 and or xor 运算后的结果最大。

    做法

    位运算中一个数的各个位上的数是不互相干扰的。

    就是说对应位置结果只和对应位置初始值有关系,所以我们打一个表,每个位置是0或1 运算后的对应结果。

    这儿有一个机灵的做法,预处理  A=0,B=(1<<31)-1 的运算结果 ,这就是天然的表了。 (挺好想的吧,一个是0的表,一个是1的……)   (这无关紧要,弄个数组也没问题的)

    表打完后采取贪心的策略,

    从高位向低位贪心。

    如果在该位上 0的结果是1 那么在这位放上0 ,如果只有1的结果是1,判断一下总和是否超过了M再累加答案。

    代码

    #include<bits/stdc++.h>
    #define MAXN 100005
    using namespace std;
    int N,M,A=0,B=(1<<31)-1,tmp,ans,sum;
    char s[5];
    int main()
    {
        scanf("%d%d",&N,&M);
        for(int i=1;i<=N;i++){
            scanf("%s%d",s,&tmp);
            if(s[0]=='A')A&=tmp,B&=tmp;
            if(s[0]=='O')A|=tmp,B|=tmp;
            if(s[0]=='X')A^=tmp,B^=tmp;
        }
        for(int i=31;i>=0;i--){
            bool f1=A&(1<<i),f2=B&(1<<i);
            if(!(f1||f2))continue;            //很不幸0和1的结果都是0
            if(f1){ans+=(1<<i);continue;}        //0的结果可以为1
            if(sum+(1<<i)<=M)ans+=(1<<i),sum+=(1<<i); //只有1的结果为1,先判断一下总和小于M 
        }
        printf("%d
    ",ans);
        return 0;
    }

    这次没有吐槽

    这题真的没有什么要注意的小细节了。

    //它和我去年看到的一道水题P2326 AKN’s PPAP很像,那个题题面也挺好玩的。

    对了,我是起床困难综合征晚期

    推送

     http://music.163.com/#/song/430053896/?userid=476005944

    悠哉日常~悠哉~悠哉

    歌手:泠鸢yousa / Hanser / 泠鸢yousaの呆萌忆

  • 相关阅读:
    matplotlib数据可视化之柱形图
    xpath排坑记
    Leetcode 100. 相同的树
    Leetcode 173. 二叉搜索树迭代器
    Leetcode 199. 二叉树的右视图
    Leetcode 102. 二叉树的层次遍历
    Leetcode 96. 不同的二叉搜索树
    Leetcode 700. 二叉搜索树中的搜索
    Leetcode 2. Add Two Numbers
    Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
  • 原文地址:https://www.cnblogs.com/Elfish/p/8075075.html
Copyright © 2011-2022 走看看