code force #443C - Short Program关于位运算
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.
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 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.
3
| 3
^ 2
| 1
2
| 3
^ 2
3
& 1
& 3
& 5
1
& 1
3
^ 1
^ 2
^ 3
0
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('\n') #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\n"); printf("| %d\n",v1); printf("& %d\n",v2); printf("^ %d\n",v3); return 0; }