code force #443C

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 b a|b  a b a^b a b a&b

1 1  1    1 1  0  1 1  1
1 0  1    1 0  1  1 0  0
0 1  1    0 1  1  0 1  0
0 0  0    0 0  0  0 0  0

按最乱来的思路来想,将同类操作合并好像就可以了,但实际上,不同位运算之间不符合一般交换律,用题目的第一个样例为示范:

设被进行位运算的数x=1;

x|3=3,x^2=1,x|1=1;

如果擅自分类,改变运算顺序:

x^2=3,x|3=3,x|1=3;

所以想要保证结果不变,最好使用两个每一位都不同的两个数来保存操作,那么我们令x=0,y=1023。
每次读取操作后,对x,y进行同步操作,最后按位比较,找出对某一位是进行了什么操作。
假如读取的第k位上,x为1,那么对于x:0->1,y为1,那么对于y:1->1,所以我们可以判断这一位进行了按位或运算。
同理,其他的结果经过简单推算,可以判断进行了何种操作。
代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int MAX=1e9+10;
const double eps=1e-4;
const double mod=1e9+7;
#define INF 0x7fffffff
#define ll long long
#define edl putchar('
')
#define useit  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define ROF(i,a,b) for(int i=a;i>=b;i--)
#define mst(a) memset(a,0,sizeof(a))
#define mstn(a,n) memset(a,n,sizeof(a))
//struct num{int x,y,k,a,b;}a[MAX];
//bool cmp(const num &x, const num &y){return x.v>y.v;}
bool cal(int a,int i)
{
    if(a&(1<<i)) return 1;
    return 0;
}
int main()
{
    int n;
    cin>>n; 
    int x=0,y=1023;
    while(n--)
    {
        char c[2];
        int t;
        scanf("%s%d",c,&t);
        if(c[0] == '|') x|=t,y|=t;
        if(c[0] == '&') x&=t,y&=t;
        if(c[0] == '^') x^=t,y^=t;
    }
    int v1=0,v2=0,v3=0;
    FOR(i,0,9)
    {
        if(!cal(x,i)&&cal(y,i))  v2+=(1<<i);
        if(cal(x,i)&&cal(y,i))   v3+=(1<<i);
        if(cal(x,i)&&!cal(y,i))  v2+=(1<<i),v3+=(1<<i);
    }
    printf("3
");
    printf("| %d
",v1);
    printf("& %d
",v2);
    printf("^ %d
",v3);
    return 0;
}
原文地址:https://www.cnblogs.com/qq936584671/p/7744381.html