题 意:
输入一个程序,这个程序包含n条语句,每一条语句都是由位运算符 ‘|’ , ‘^’ , ‘&’ ,加一个操作数xi组合而成。要求把程序语句缩短为不超过5句.
输入限制:
1<=n<=5e5
0<=xi<=1023
样例输入:
3
| 3
^ 2
| 1
样例输出:
2
| 3
^ 2
样例输入:
3
& 1
& 3
& 5
样例输出:
1
& 1
思 路:题目有提示,1024和位运算符,就应该想到二进制运算(关键点1),对每一位来进行分析,经过位运算后,只可能从0边为1,或者从1变为0两种情况,先设number0 = 0,number1=1023。来看看经过程序操作后,0和1的变化。变化有四种情况:
1.0->0 1->1
那么|0,&1,^0可以实现这种变化
2.0->0 1->0
那么&0可以实现这种变化
3.0->1 1->1
那么 |1可以实现这种变化
4.0->1 1->0
那么^1可以实现这种变化
接下来一个重点是顺序问题,先确定好顺序,这样后面的操作不会对前面的操作有影响。很显然,顺序选先and 再 xor 再 or是个简单的操作 至少显然可以看出 (XOR和OR不会对AND有影响 这个地方可能又有点难理解,看代码就会明朗很多) 还要考虑AND对XOR和OR的影响。
//得自己ebug
//按奇 偶去炸
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 5e5+5;
typedef long long ll;
char s[maxn][2];
int d[maxn];
int n;
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s %d",s[i],&d[i]);
}
int number0 = 0,number1 =1023;
for(int i=0;i<n;i++){
if(s[i][0] == '|'){
number0=number0|d[i];
number1=number1|d[i];
}else if(s[i][0] == '^'){
number0=number0^d[i];
number1=number1^d[i];
}else{
number0=number0&d[i];
number1=number1&d[i];
}
}
int base = 1,XOR = 0,OR = 0,AND = 0;
for(int i=0;i<10;i++){
int low0 = number0&1;
int low1 = number1&1;
if(low0 == 0){
if(low1 == 0){
;
}else{
AND=AND|base;
}
}else{
if(low1 == 0){ //如果不加 那么首先先要AND 0对结果有影响
AND = AND|base; //消除AND对这个的XOR的影响
XOR=XOR|base;
}else{
OR=OR|base; //AND对OR每影响
}
}
base<<=1;
number0>>=1;
number1>>=1;
}
printf("3\n");
printf("& %d\n^ %d\n| %d\n",AND,XOR,OR);
return 0;
}