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。这样的话ci=ai&ai1+ai|ai1,则设di=cibi=ai&ai1,由此可以知道a数组相邻两个数进行与以及或得到的结果,排除掉了加法产生的进位的影响后,位与位之间就彼此不相关,可以套路地进行按位分析了。如果枚举a1的每一位,根据前面得到的结论实际上就能够唯一确定出a2,a3..an的这一位的值(当然可能不存在),由此也就知道了整个a数组。所以现在要做的就是从高往低或者从低往高枚举a1的每一位,这一位可以为0也可以为1,如果这一位为0成立(即设这一位为0,可以依次得到a2,a3..an的这一位而不引起矛盾)为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 @   脂环  阅读(54)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
主题色彩