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

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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值