• [NOI2014]起床困难综合症


    原题链接:https://www.luogu.org/problemnew/show/P2114

    NOI的水题

    题意简述:给出n个指令,在0到m之中选出一个数,使其执行这n个指令后值最大。

    一共有三种指令:“和”“或”“异或”,而一个数在二进制下执行三种指令时,各位之间是不能互相影响的。

    有一个简单的结论,在二进制中,第x位为1,之后的y位全为0,大于第x位为0,之后y位全为1(“之后”指低位)

    非常简单的一个结论,想不明白的请去复习等比数列求和。

    将m转化为二进制,从高到低枚举初始数字二进制表示的每一位,有0和1两种选法,会出现如下几种情况:

    之前选择的每一位均与m相同,且m中这一位为0:答案中这一位也为0

    之前选择的每一位均与m相同,且m中这一位为1:选0或是选1均可,优先选择能使结果中这一位为1的。如果选择0或1均可,选择0

    之前选择的与m不同,则答案中这一位选0和1均可,同样优先选择能使结果中这一位为1的

    #include<cstdio>
    using namespace std;
    int n,m,x,l;
    int c[35],ans[35],num[35][3];
    char s[5];
    long long sum;
    int main()
    {
    //    freopen("testdata.in","r",stdin);
        scanf("%d %d",&n,&m);
        for(int i=0;i<33;i++)
        {
            num[i][0]=0;
            num[i][1]=1;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%s %d",s,&x);
            l=-1;
            for(int j=0;j<33;j++) c[j]=0;
            while(x)
            {
                c[++l]=x%2;
                x>>=1;
            }
            for(int j=0;j<33;j++)
            {
                if(s[0]=='A')
                {
                    num[j][0]=num[j][0]&c[j];
                    num[j][1]=num[j][1]&c[j];
                }
                if(s[0]=='O')
                {
                    num[j][0]=num[j][0]|c[j];
                    num[j][1]=num[j][1]|c[j];
                }
                if(s[0]=='X')
                {
                    num[j][0]=num[j][0]^c[j];
                    num[j][1]=num[j][1]^c[j];
                }
            }    
        }
        l=-1;
        for(int i=0;i<33;i++) c[i]=0;
        while(m)
        {
            c[++l]=m%2;
            m>>=1;
        }
        for(int i=32;i>=0;i--)
        {
            ans[i]=0;
            if(c[i]==0) ans[i]=num[i][0];
            else if(c[i]==1)
            {
                if(num[i][0]==1)
                {
                    ans[i]=1;
                    for(int j=i-1;j>=0;j--) c[j]=1;
                }
                if(num[i][1]==1) ans[i]=1;
                if(num[i][0]==0&&num[i][1]==0)
                {
                    for(int j=i-1;j>=0;j--) c[j]=1;
                }
            }
        }
        for(int i=0;i<=32;i++) sum+=(ans[i]<<i);
        printf("%lld",sum);
        return 0;
    }
  • 相关阅读:
    VS2012打包部署Winform程序
    WPF 触发器Triggers
    VS2010中的顺序图
    decimal,float和double的区别
    EXCEL基本知识
    java byte 循环左移 循环右移 rotateLeft rotateRight
    博客地址转移
    PHP学习思维导图
    一款web前端在线编辑器
    9patch android .9格式使用
  • 原文地址:https://www.cnblogs.com/zeroform/p/8372223.html
Copyright © 2020-2023  润新知