题目链接:https://ac.nowcoder.com/acm/problem/213756

到主站看:https://blog.csdn.net/weixin_43346722/article/details/109953092

题目

scimoon 有一个坏掉的计算器,这个计算器仅接受 的数

这个计算器只支持一种操作,举个例子,输入一个数 ,这个数会按顺序进行 次操作,在第 次操作中,有一个操作符 和一个数

如果 表示这次操作是将数 与运算

如果 表示这次操作是将数 或运算

如果 表示这次操作是将数 异或运算

操作过后 将会变为运算的结果

scimoon 觉得这个计算器非常地慢,于是他想对这 个运算做一些简化,这个艰巨的任务交给了你

具体而言,你的任务是:用不超过 次上面的操作,使得对于任何 ,你的操作的输出与计算器的输出一致

可以证明必然存在解

可能存在多组解,你只需要输出一组可能的解即可

输入

第一行一个整数 ,表示计算器的操作次数

接下来 行,每行两个整数 ,按顺序描述了每次操作

输出

第一行一个 ,表示你的操作次数

你必须保证你输出的

接下来 行每行仿照输入中 的格式输出每次操作

样例输入

1
1 14514

样例输出

1
1 14514

数据范围

思路

这道题。。。二进制运算吧。
挺烦的。

我们首先可以想到,如果相邻的两个运算是同一个类型,我们完全可以合并,用的运算就是他们要的运算。(就是
然后我们大概也可以看出是要最后只剩下每种各一个,那我们就来看怎么弄。

首先,确定顺序:
我们来看看每个操作的本质。异或就决定要不要取反,那我们可以放在最后面。或就是它的 会起决定性作用,那我们可以把它摆在第二个。那与就摆在第一个了。

接着我们来看每个操作中的 分别会对我们最终三个操作产生什么改变。

  1. 异或操作。由于我们最后一个操作也是异或,就可以直接合并在一起
  2. 或操作。那或操作我们就一位一位看。
    如果这一位是 ,那上面试怎样就是怎样,我们不用管。
    如果这一位是 ,那这一位就一定是 ,就把与和或的这一位都改成 ,异或改成
  3. 与操作。同样,也一位一位看。
    如果这一位是 ,那上面试怎样就是怎样,我们不用管。
    如果这一位是 ,那这一位就一定是 ,就把与、或、异或都改成

那最后输出简化得到的三个运算即可。

代码

#include<cstdio>

using namespace std;

int n, huo, yu = -1, yihuo, op, a, ans[3], size[3];
bool yuyes;

int main() {
    scanf("%d", &n);
    for (int times = 1; times <= n; times++) {
        scanf("%d %d", &op, &a);

        if (op == 1) {//与操作
            if (!yuyes) {
                yuyes = 1;
                yu = a;
            }

            for (int i = 0; i <= 25; i++)
                if ((a >> i) % 2 == 0) {
                    if ((yu >> i) % 2) yu -= 1 << i;
                    if ((yihuo >> i) % 2) yihuo -= 1 << i;
                }

            continue;
        }
        if (op == 2) {//或操作
            for (int i = 0; i <= 25; i++)
                if ((a >> i) % 2) {
                    huo |= 1 << i;
                    if (yu != -1) yu |= 1 << i;
                        else yu = 1 << i;
                    if ((yihuo >> i) % 2) yihuo -= 1 << i; 
                    yuyes = 1;
                }

            continue;
        }
        if (op == 3) {//异或操作
            yihuo ^= a;
        }
    }

    if (huo != 0) {
        ans[++ans[0]] = huo;
        size[1] = 2;
    }
    if (yu != -1) {
        ans[++ans[0]] = yu;
        size[ans[0]] = 1;
    }
    if (yihuo != 0) {
        ans[++ans[0]] = yihuo;
        size[ans[0]] = 3;
    }

    printf("%d\n", ans[0]);
    for (int i = 1; i <= ans[0]; i++) printf("%d %d\n", size[i], ans[i]);

    return 0;
}