Loading

2021牛客暑期多校训练营8 D. OR(位运算/结论)

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

题目描述

There are two sequences of length n−1n−1, b=(b2,b3,…,bn)b=(b2,b3,…,bn), c=(c2,c3,…,cn)c=(c2,c3,…,cn). Here, each bibi,cici is a non-negative integer.

Now, the sequence a=(a1,a2,…,an)a=(a1,a2,…,an) considers beautiful if and only if forall ii (2≤i≤n)(2≤i≤n), bi=ai−1 or aibi=ai−1orai, ci=ai−1+aici=ai−1+ai and each aiai is a non-negative integer.

Now, Toilet-Ares asks you to calculate the number of beautiful sequences.

输入描述:

The first line contains one integer nn (2≤n≤105)(2≤n≤105) - the length of sequence aa.

The second line contains n−1n−1 integers b2,b3,…,bnb2,b3,…,bn (0≤bi<230)(0≤bi<230) - the elements of sequence bb.

The third line contains n−1n−1 integers c2,c3,…,cnc2,c3,…,cn (0≤ci<231)(0≤ci<231) - the elements of sequence cc.

输出描述:

Print one number - the number of beautiful sequences.

示例1

输入

复制

4
7 5 5
7 9 5

输出

复制

2

做这个题关键就是要知道一个性质\(x + y = x \& y + x | y\)。这样的话\(c_i = a_i \& a_{i-1} + a_i | a_{i-1}\),则设\(d_i=c_i-b_i=a_i\& a_{i-1}\),由此可以知道a数组相邻两个数进行与以及或得到的结果,排除掉了加法产生的进位的影响后,位与位之间就彼此不相关,可以套路地进行按位分析了。如果枚举\(a_1\)的每一位,根据前面得到的结论实际上就能够唯一确定出\(a_2,a_3..a_n\)的这一位的值(当然可能不存在),由此也就知道了整个a数组。所以现在要做的就是从高往低或者从低往高枚举\(a_1\)的每一位,这一位可以为0也可以为1,如果这一位为0成立(即设这一位为0,可以依次得到\(a_2,a_3..a_n\)的这一位而不引起矛盾)为1也成立,由乘法原理将答案乘2,如果为0为1都不成立则答案为0且终止循环,否则对答案没有贡献,答案不变。

#include <bits/stdc++.h>
using namespace std;
int n, a[100005], b[100005], c[100005], d[100005];
int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 2; i <= n; i++) cin >> b[i];
	for(int i = 2; i <= n; i++) cin >> c[i];	
	for(int i = 2; i <= n; i++) {
		d[i] = c[i] - b[i];
	}
	long long ans = 1;
	for(int i = 0; i < 30; i++) {//枚举a[1]的每一位 要么为0要么为1
		bool zero = 1, one = 1;
		vector<int> v(n + 1);//用来存储a1到an第i位的结果
		v[1] = 0;//a1的第i位为0的话
		for(int j = 2; j <= n; j++) {//判断是否合法
			int nb = (b[j] >> i) & 1, nd = (d[j] >> i) & 1;//获取b数组和d数组第j个元素的第i位
			if(nd) {
				if(nb) {//aj-1和aj的第i位相与为1 相或也为1
					if(v[j - 1]) {//如果aj-1的第i位是1
						v[j] = 1;//aj的第i位也是1
					} else {//否则根据与或的性质就有矛盾了
						zero = 0;
						break;
					}
				} else {//相与为1相或为0,必然不可能
					zero = 0;
					break;
				}
			} else {
				if(nb) {
					if(v[j - 1]) {
						v[j] = 0;
					} else {
						v[j] = 1;
					}
				} else {
					if(v[j - 1]) {
						zero = 0;
						break;
					} else {
						v[j] = 0;
					}
				}
			}
		}
		v[1] = 1;//a1的第i位为1的话
		for(int j = 2; j <= n; j++) {
			int nb = (b[j] >> i) & 1, nd = (d[j] >> i) & 1;
			if(nd) {
				if(nb) {
					if(v[j - 1]) {
						v[j] = 1;
					} else {
						one = 0;
						break;
					}
				} else {
					one = 0;
					break;
				}
			} else {
				if(nb) {
					if(v[j - 1]) {
						v[j] = 0;
					} else {
						v[j] = 1;
					}
				} else {
					if(v[j - 1]) {
						one = 0;
						break;
					} else {
						v[j] = 0;
					}
				}
			}
		}
		if(zero && one) ans *= 2;
		else if(zero ^ one) ans *= 1;
		else {
			ans = 0;
			break;
		}
	}
	cout << ans;
	return 0;
}
posted @ 2021-08-09 21:03  脂环  阅读(54)  评论(0编辑  收藏  举报