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=ai∣ai−1, c i = a i + a i − 1 c_i=a_i+a_{i-1} ci=ai+ai−1
求满足条件的数组 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=(ai∣ai−1)+(ai&ai−1)
那么其实可以得到 d i = c i − b i = a i & a i − 1 d_i=c_i-b_i=a_i\\&a_{i-1} di=ci−bi=ai&ai−1
于是可以按照二进制的每一位考虑,不同的位之间互不影响
枚举 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} ai−1,可以得到 a i a_i ai的这一位二进制是 0 0 0还是 1 1 1
比如当 a i − 1 a_{i-1} ai−1第 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} ai−1第 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的主要内容,如果未能解决你的问题,请参考以下文章