• codeforces 879c


    C. Short Program
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Petya learned a new programming language CALPAS. A program in this language always takes one non-negative integer and returns one non-negative integer as well.

    In the language, there are only three commands: apply a bitwise operation AND, OR or XOR with a given constant to the current integer. A program can contain an arbitrary sequence of these operations with arbitrary constants from 0 to 1023. When the program is run, all operations are applied (in the given order) to the argument and in the end the result integer is returned.

    Petya wrote a program in this language, but it turned out to be too long. Write a program in CALPAS that does the same thing as the Petya's program, and consists of no more than 5 lines. Your program should return the same integer as Petya's program for all arguments from 0 to 1023.

    Input

    The first line contains an integer n (1 ≤ n ≤ 5·105) — the number of lines.

    Next n lines contain commands. A command consists of a character that represents the operation ("&", "|" or "^" for AND, OR or XOR respectively), and the constant xi 0 ≤ xi ≤ 1023.

    Output

    Output an integer k (0 ≤ k ≤ 5) — the length of your program.

    Next k lines must contain commands in the same format as in the input.

    Examples
    input
    3
    | 3
    ^ 2
    | 1
    output
    2
    | 3
    ^ 2
    input
    3
    & 1
    & 3
    & 5
    output
    1
    & 1
    input
    3
    ^ 1
    ^ 2
    ^ 3
    output
    0
    Note

    You can read about bitwise operations in https://en.wikipedia.org/wiki/Bitwise_operation.

    Second sample:

    Let x be an input of the Petya's program. It's output is ((x&1)&3)&5 = x&(1&3&5) = x&1. So these two programs always give the same outputs.

    这个题怎么讲呢,网上很多题解都用的一种方法,这就很没有意思,这时候我先讲一下我用的方法,可能比较蠢,实现起来也挺麻烦,不过好歹是a了

    题意:这是一个程序,只会三种操作&、|、^,   先输入一个n,说明有n个操作,

    直接看数据  

    3
    | 3
    ^ 2
    | 1 这个就意味着某个数x进行了三次操作,分别是x|3之后再x^2,在x|1,现在让你根据结果进行转换成至多5部操作的集合,
    就是说上面的一系列步骤,我们可以化成x|3再x^2的两步操作

    当然这个操作可能会有很多,就是让你转化成5步以内的操作


    好了讲思路了,首先这个题要一位一位的算,这个是我首先想到的,一位一位的操作,最后进行组合,就是我的思路;
    首先看这个东西 x的某一位 或0 和 与1 都不会改变这一位 对吧
    再看 x的某一位 或1 和 与0 都会使这一位必定发生改变 对吧
    当这一位必定发生改变的时候,我之前在这一位上的所有操作都没了意义对吧,因为前面无论我怎么操作,我最后只要在这一位上|1或&0,那么这位的值就是确定的

    若是我在这一位上进行|0和&1操作,这一位的值不会发生改变,那么我们就可以跳过这个操作

    也就是说我只要纪录下异或的操作就行了,每当我遇见&0和|1的时候我就清空我纪录的异或操作


    拿这个例子
    3
    | 3
    ^ 2
    | 1

    看到我的操作思路首先看 这是个或,或的是0000000011(二进制),那么就是说我的第一位和第二位必定会发生改变,我就把我的第一位和第二位更新成1,
    再看第二步 异或0000000010 把0存进第1位的数组里面(装的是异或的操作 就是说第1位第1次异或0),
                       把1存进第2位的数组里面(就是说第2位第1次异或1)............
    接下来看第三步 或0000000001 第一位是1就是说我的第一位必定会变成1,于是第一位前面的异或操作都可以清除了,因为这一位必定变成1,
    其他位是0就是说我的其他位保持不变,
    这时候我们的x第一位是1,异或操作的集合为空,第二位是1,异或操作的集合是{1},第三位...........
    首先我们肯定是先进行或操作和与操作,还是那句话,确定了这一位是|1还是&0,前面的所有操作都没了意义,而|0和&1我又可以忽略,因为他们不改变这一位上的值
    所以先进性或和与操作,最后才轮到异或操作
    先看这一位上是1还是0,如果确定是1那么这一位就|1,就是说假设我现在知道第一位和第三位是1,那么我就|5就可以了,这样的话第一位和第三位就变成了1,而其他的位不会发生改变
    若是这一位上是0,那么我就进行&操作,就是说我现在确定了第一位和第三位是0,那么我就可以&1111111010这样就把第一位和第三位变成了0,其他位不发生改变
    最后处理每一位的异或操作集合,假设第一位的异或集合是{0,1,0}(这里说一下,异或操作是符合交换律和结合律的),那么第一位最后就是异或上1(0^1^0 = 1),若是这位的
                   假设第二位的异或集合是{0,0},那么第二位最后异或0(0^0 = 0)
    最后把每一位异或1的加起来:假设第一位异或1,第三位异或1,其他位异或0,那么我最后异或5即可


    丑陋的代码:

    #include <iostream>

    #include <cstdio>

    #include <queue>

    using namespace std;

    int arr[16];//纪录某一位上的值   这一位上是-1代表从来没发生过&0|1的操作

    vector<int>  p[16];//纪录某一位上的异或操作,每当遇见|1&0时清空

    int pp[16];//纪录p[16]异或操作的结果

    int main()

    {

        int n,i,j,k,x;

        int res = 0;

        char a = '&',b = '|',c = '^';

        char ch;

        scanf("%d",&n);

        for(i = 0; i < 16; ++i)

            arr[i] = -1;

        //赋上初值

        for(int c = 0; c < n; ++c)

        {

            getchar();

            ch = getchar();

            scanf("%d",&k);

            for(i = 1,j = 1; i < 1024; (i <<= 1),++j)

            {

                if((i&k) && ch == '|')

                {

                    //|1时进行处理

                    arr[j] = 1;

                    p[j].clear();

                }

                else if((i&k) == 0 && ch == '&')

                {

                    //&0时进行处理

                    arr[j] = 0;

                    p[j].clear();

                }

                else if(ch == '^')

                {

                    //插入异或操作

                    if((i&k))

                        x = 1;

                    else

                        x = 0;

                    p[j].push_back(x);

                }

            }

        }

        for(i = 1; i < 16; ++i)

        {

            int d = 0;

            for(j = 0; j < p[i].size(); ++j)

                d ^= p[i][j];

            pp[i] = d;

            //求每一位异或操作的最后结果

        }

        printf("3 ");

        for(i = 1; i < 16; ++i)

        {

            //判断哪一位被强制转换成了1   这一位|1即可

            if(arr[i] == -1)

                continue;

            if(arr[i] == 1)

                res += 1<<(i-1);

        }

        printf("| %d ",res);

        res = 0;

        for(i = 1; i < 16; ++i)

        {

            //判断哪一位被强制转换成了0   这一位&0即可

            if(arr[i] == -1)

                continue;

            if(arr[i] == 0)

            {

                res += 1<<(i-1);

            }

        }

        res = 1023^res;

        printf("& %d ",res);

        res = 0;

        for(i = 1; i < 16; ++i)

        {

            //最后输出每一位异或1的和

            //就是第一位和第三位是1,其他位是0,输出^5

            if(pp[i] == 1)

            {

                res += 1<<(i-1);

            }

        }

        printf("^ %d ",res);

    }

     

    -------------------------------------------------------------------------

    之后我在看看别人的那个解法,想明白了今后再补上

     

  • 相关阅读:
    nexus搭建maven私服及私服jar包上传和下载
    Java数据结构和算法(八)——递归
    postgresql数据库的 to_date 和 to_timestamp 将 字符串转换为时间格式
    postgreSql的字段名称是小写的这个一定要注意
    Mybatis异常There is no getter for property named 'XXX' in 'class java.lang.String'
    postgresql 获取所有表名、字段名、字段类型、注释
    克隆指定的分支和切换分支
    git branch不显示本地分支的问题
    git中Please enter a commit message to explain why this merge is necessary.
    企业微信开发步骤 1.拿到企业的id,在我的企业,拖到最下面拿到企业id 2.拿到SECRET,这个secret只有先创建应用才会产生出来
  • 原文地址:https://www.cnblogs.com/mltang/p/7841139.html
Copyright © 2020-2023  润新知