二进制

链接:https://ac.nowcoder.com/acm/contest/8564/B
来源:牛客网

题目描述
scimoon 有一个坏掉的计算器,这个计算器仅接受 0\sim 2^{20}-10∼2
20
−1 的数

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

和一个数 a_ia
i

如果 op_i=1op
i

=1 表示这次操作是将数 x 与 a_ia
i

做 与运算

如果 op_i=2op
i

=2 表示这次操作是将数 x 与 a_ia
i

做 或运算

如果 op_i=3op
i

=3 表示这次操作是将数 x 与 a_ia
i

做 异或运算

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

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

具体而言,你的任务是:用不超过 5 次上面的操作,使得对于任何 0\le x\le 2^{20}-10≤x≤2
20
−1,你的操作的输出与计算器的输出一致

可以证明必然存在解

可能存在多组解,你只需要输出一组可能的解即可
输入描述:
第一行一个整数 n,表示计算器的操作次数

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

输出描述:
第一行一个 m,表示你的操作次数

你必须保证你输出的 m\le 5m≤5

接下来 m 行每行仿照输入中 op\ aop a 的格式输出每次操作
示例1
输入
复制
1
1 14514
输出
复制
1
1 14514
备注:
n\le 5\times 10^5,1\le op\le 3,0\le a\le 2^{20}-1n≤5×10
5
,1≤op≤3,0≤a≤2
20
−1

我们发现,与运算,或运算,异或运算都是按照位来算的,所以每一位在经历过那么多次运算后,对于具体的每一位,只需要看每一位是如何变化的,然后针对这一位进行具体的操作

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 5e5 + 10;

int op[N], a[N];

int main(){
	int n;
	scanf("%d", &n);
	
	for (int i = 1; i <= n; i ++){
		scanf("%d%d", &op[i], &a[i]);
	}
	
	int AND = (1 << 20) - 1;
	int OR = 0;
	int XOR = 0;
	//cout << AND << endl;
	for (int i = 0; i < 20; i ++){
	    int x = 0, y = 1;
		for (int j = 1; j <= n; j ++){
			int temp = a[j] >> i & 1;
			if (op[j] == 1){
				x &= temp;
				y &= temp;	
			}
			else if (op[j] == 2){
				x |= temp;
				y |= temp;
			}
			else if (op[j] == 3){
				x ^= temp;
				y ^= temp;
			}
		}
		
	//	cout << x << "------" << y << endl;
	//	cout << i << endl;
		if (x == 0 && y == 0)    AND -= (1 << i);
	//	cout << AND << endl;
		if (x == 1 && y == 1)    OR += (1 << i);
		if (x == 1 && y == 0)    XOR += (1 << i);	
	}
	
	int cnt = 0;
	if (AND != (1 << 20 - 1))   cnt ++;
	if (OR != 0)   cnt ++;
	if (XOR != 0)  cnt ++;
	
	cout << cnt << endl;
	
	if (AND != (1 << 20 - 1))   cout << "1 " << AND << endl;
	if (OR != 0)   cout << "2 "<< OR << endl;
	if (XOR != 0)  cout << "3 "<< XOR << endl;
	
	return 0;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值