codeforce -897C

codeforce-897C

题 意:
输入一个程序,这个程序包含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;
}

猜你喜欢

转载自blog.csdn.net/qq_37129433/article/details/81095627