zoukankan      html  css  js  c++  java
  • [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,胜过其它所有低位为1的和

    于是此题很显然可以贪心来解决

    我一开始的策略是把每一位尝试进入1或0,看得到的答案

    但实际上有更为好写的方法,我们将一个全1串,和一个全0串放入操作,就可以得到我所想要的

    最后我们从最高位开始贪心

      如果该位上的0进入得到1,那么一定选0

      不然如果该位上的1进入得到1,那么一定选1

      如果不满足上述则选0

    实现如下:

    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <map>
    #include <string>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        register int p(1),a(0);register char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
        if(ch=='-') p=-1,ch=getchar();
        while(ch>='0'&&ch<='9') a=a*10+ch-48,ch=getchar();
        return a*p;
    }
    int n,m,op1=-1,op2=0,num=0,ans=0;
    char a[100];
    int main()
    {
    //    freopen("input","r",stdin);
    //    freopen("output","w",stdout);
        n=read(),m=read();
        for(int i=1;i<=n;i++)
        {
            scanf("%s",a);num=read();
            if(a[0]=='A') op1&=num,op2&=num;
            else if(a[0]=='O') op1|=num,op2|=num;
            else  op1^=num,op2^=num;
        }
        for(int i=29;i>=0;i--)
        {
            if((1<<i)&op2) ans+=(1<<i);
            else if((1<<i)<=m&&(1<<i)&op1) m-=(1<<i),ans+=(1<<i);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    【SCOI 2011】 糖果
    【POJ 3159】 Candies
    【POJ 1716】 Integer Intervals
    【POJ 2983】 Is the information reliable?
    【POJ 1364】 King
    【POJ 1201】 Intervals
    【POJ 1804】 Brainman
    6月10日省中提高组题解
    【POJ 3352】 Road Construction
    【POJ 1144】 Network
  • 原文地址:https://www.cnblogs.com/cold-cold/p/10035826.html
Copyright © 2011-2022 走看看