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 ≤ 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
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;
}