2021牛客暑期多校训练营8 D.OR

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营8 D.OR相关的知识,希望对你有一定的参考价值。

题意

给定 b i = a i ∣ a i − 1 b_i=a_i|a_{i-1} bi=aiai1, c i = a i + a i − 1 c_i=a_i+a_{i-1} ci=ai+ai1

求满足条件的数组 a a a有多少个


c i = ( a i ∣ a i − 1 ) + ( a i & a i − 1 ) c_i=(a_i|a_{i-1})+(a_i\\&a_{i-1}) ci=(aiai1)+(ai&ai1)

那么其实可以得到 d i = c i − b i = a i & a i − 1 d_i=c_i-b_i=a_i\\&a_{i-1} di=cibi=ai&ai1

于是可以按照二进制的每一位考虑,不同的位之间互不影响

枚举 a 1 a_1 a1的二进制第 i i i位是 0 0 0还是 1 1 1

然后根据 b i b_i bi d i d_i di a i − 1 a_{i-1} ai1,可以得到 a i a_i ai的这一位二进制是 0 0 0还是 1 1 1

比如当 a i − 1 a_{i-1} ai1 k k k位二进制为 1 1 1,那么显然 a i a_{i} ai的第 k k k位二进制就是 d i d_i di的第 k k k位二进制

a i − 1 a_{i-1} ai1 k k k位二进制为 0 0 0,那么显然 a i a_{i} ai的第 k k k位二进制就是 b i b_i bi的第 k k k位二进制

然后再根据得到的 a i a_i ai这一位的二进制,去验证是否同时满足 b i , d i b_i,d_i bi,di数组

然后按照每一位的方案乘起来即可

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 3e5+10;
const int mod = 1e9+7;
int n,b[maxn],c[maxn],d[maxn];
int isok(int x)//第x位二进制位 
{
	int ans = 0;
	for(int can = 0; can<=1; can++ )
	{
		int las = can, flag = 1;//上一次a在这一位二进制是0还是1 
		for(int i=2;i<=n;i++)
		{
			int q = ( b[i]>>x )&1, w = ( d[i]>>x )&1;
			if( las==0 )//或起来为0这一位也是0,为1这一位就是1
			{
				if( (q&las)!=w )	flag = 0;
				las = q;
			}
			else //与起来是1这一位也是1,与起来为0这一位也是0
			{
				if( (w|las)!=q )	flag = 0;
				las = w;	
			}	
		}
		ans += flag;
	}	
	return ans;
}
signed main()
{
	int ans = 1;
	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];
	for(int i=0;i<=30;i++)	ans = ans*isok( i )%mod;
	cout << ans;
} 

以上是关于2021牛客暑期多校训练营8 D.OR的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营10,签到题FH

2021牛客暑期多校训练营9,签到题HE

2021牛客暑期多校训练营8 F.Robots 离线分治+bitset

2021牛客暑期多校训练营 2

2021牛客暑期多校训练营1, 签到题DFBG

2021牛客暑期多校训练营1 - F - Find 3-friendly Integers - 题解