2021牛客多校第八场D

本文介绍了一种解决方法,通过枚举a1的取值,利用位操作技巧分析给定的两个非负序列b和c之间的关系,找出满足b[i]=a[i-1]|a[i]和c[i]=a[i-1]+a[i]的a序列个数。关键在于理解a1对后续序列的决定作用和位运算的应用。
摘要由CSDN通过智能技术生成

题意:给两个长度为n-1的非负序列(b2,b3...bn)(c2,c3...cn),求满足下列条件的a序列有多少个:

1.b[i]=a[i-1]|a[i];2.c[i]=a[i-1]+a[i]

思路:

显然c[i]-b[i]=a[i-1]&a[i](因为a&b+a|b=a+b)

因为对于a序列,a1一旦确定,就能根据c序列确定整个序列,所以我们枚举a1可能的取值就行

具体就是枚举a1的每一位能取0或者1

lasno0=1代表a[j-1]的第i位不能取0,lasno1=1a[j-1]的第i位代表不能取1;

nowno0=1代表a[j]的第i位不能取0,nowno1=1a[j]的第i位代表不能取1;

枚举从2到n,只有始终 &=0并且|=1 时a1的第i位可以取01两种结果(所以判断lasno1,lasno0就能判断是不是需要乘2)

如果出现 &=0,|=1 则不可能有这样的a1

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int  b[N], c[N];

int main()
{
	int n;
	cin >> n;
	for (int i = 2; i <= n; i++)
	{
		scanf("%d", &b[i]);
	}
	for (int i = 2; i <= n; i++)
	{
		scanf("%d", &c[i]);
		c[i] -= b[i];
	}
	int ans = 1; 
	for (int i = 0; i < 31; i++)
	{
		int lasno0 = 0, lasno1 = 0;
		for (int j = 2; j <= n; j++)
		{
			int nowno0 = 0, nowno1 = 0;
			int And = (c[j] >> i) & 1, Or = (b[j] >> i) & 1;
			if (And == 0 && Or == 0)
			{
				if (lasno0)
				{
					ans = 0;
					break;
				}
				nowno1 = 1;
			}
			else if (And == 1 && Or == 1)
			{
				if (lasno1)
				{
					ans = 0;
					break;
				}
				nowno0 = 1;
			}
			else if (And == 1 && Or == 0)
			{
				ans = 0;
				break;
			}
			else
			{
				nowno0 = lasno1;
				nowno1 = lasno0;
			}
			lasno0 = nowno0;
			lasno1 = nowno1;
			//cout<< lascnt << nowcnt << endl;
		}
		if (ans)
		{
			if (!lasno1&&!lasno0)//只有一直是01都可以取才有两种可能
			{
				ans <<= 1;
				//cout << ans << endl;
			}
		}
		else
		{
			break;
		}
	}
	cout << ans << endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值