Codeforces Round #443 (Div. 2) C. Short Program

来源:互联网 发布:java开发的wms系统 编辑:程序博客网 时间:2024/05/18 19:46

C. Short Program

Problem Statement

    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 ≤ 5105) — 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

Example 1
    Input
        3
        | 3
        ^ 2
        | 1
    Output
        2
        | 3
        ^ 2
Example 2
    Input
        3
        & 1
        & 3
        & 5
    Output
        1
        & 1
Example 3
    Input
        3
        ^ 1
        ^ 2
        ^ 3
    Output
        0

Note

    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.

题意

    给你n个操作,每个操作是and,or或xor上一个值,我们将这么一个函数称作f(x),我们需要构造出一个函数g(x),这个函数的操作数小于等于5,并且对于任何x,0≤x≤1023,f(x)==g(x)。

思路

    对于and,or和xor一个值之后,一个bit位上的状态有4种可能: 1.必定为0 ; 2. 必定为1 ; 3.与原数相等 ; 4.与原数相反 ; 而如果该位必定为0,则表示它and上了一个该位为0的数,必定为1则表示它or上了一个该位为1的数,与原数相等和相反则是通过xor来完成。所以我们只需要3次操作就行了(其实只需要两次就能做到。)所以我们只要统计一下各种状态的个数就行了。

Code

#pragma GCC optimize(3)#include<bits/stdc++.h>using namespace std;typedef long long ll;bool Finish_read;template<class T>inline void read(T &x) {    Finish_read=0;x=0;int f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();    x*=f;Finish_read=1;}template<class T>inline void print(T x) {    if(x/10!=0)        print(x/10);    putchar(x%10+'0');}template<class T>inline void writeln(T x) {    if(x<0)        putchar('-');    x=abs(x);    print(x);    putchar('\n');}template<class T>inline void write(T x) {    if(x<0)        putchar('-');    x=abs(x);    print(x);}/*================Header Template==============*/char op[2];int x,vis[15],n;// 1: is 1;  2: is 0;  3: diff with x;  4: same as x;int main() {    read(n);    for(int i=0;i<10;i++)        vis[i]=4;    for(int i=1;i<=n;i++) {        scanf("%s",op+1);        read(x);        if(op[1]=='|') {            int pos=0;            while(x) {                if(x&1)                    vis[pos]=1;                pos++;                x>>=1;            }        }        else if(op[1]=='&') {            for(int i=9;i>=0;i--) {                int tmp=(1<<i);                if(x>=tmp)                    x-=tmp;                else                    vis[i]=2;            }        }        else {            int pos=0;            while(x) {                if(x&1) {                    if(vis[pos]==0)                        vis[pos]=3;                    if(vis[pos]==1||vis[pos]==2)                        vis[pos]=3-vis[pos];                    if(vis[pos]==3||vis[pos]==4)                        vis[pos]=7-vis[pos];                }                pos++;                x>>=1;            }        }//  for(int i=0;i<10;i++)cout<<vis[i]<<" ";//  cout<<endl;    }    writeln(3);    int t=0;    for(int i=0;i<10;i++)        if(vis[i]==1)            t^=(1<<i);    printf("| %d\n",t);    t=1023;    for(int i=0;i<10;i++)        if(vis[i]==2)            t^=(1<<i);    printf("& %d\n",t);    t=0;    for(int i=0;i<10;i++)        if(vis[i]==3)            t|=(1<<i);    printf("^ %d\n",t);    return 0;}
原创粉丝点击