Problem Analysis

题目给给定数组牛客多校8.D.OR 二进制+思维_acm竞赛​​各具有牛客多校8.D.OR 二进制+思维_c++_02​个元素,求满足牛客多校8.D.OR 二进制+思维_算法_03条件的的具有牛客多校8.D.OR 二进制+思维_ios_04个元素的牛客多校8.D.OR 二进制+思维_数组_05​序列的个数。

拿到题目没啥思路,和队友讨论只需要确定牛客多校8.D.OR 二进制+思维_数组_05​​序列的首个元素,后面元素即可唯一确定,发现确实是正确的,但对于首元素的枚举方法如果纯暴力肯定会T,遂向学长求救,得知了神奇的结论:
牛客多校8.D.OR 二进制+思维_acm竞赛_07
附赠一个证明过程:
牛客多校8.D.OR 二进制+思维_数组_08

牛客多校8.D.OR 二进制+思维_算法_09

然后通过列真值表,可以证明牛客多校8.D.OR 二进制+思维_c++_10成立。​

那么我们现在可以得出牛客多校8.D.OR 二进制+思维_算法_11数组(即为牛客多校8.D.OR 二进制+思维_数组_12​),以及牛客多校8.D.OR 二进制+思维_c++_13(即为牛客多校8.D.OR 二进制+思维_ios_14​),因此我们可以根据这两个数组求牛客多校8.D.OR 二进制+思维_算法_15

从最低位开始,每次枚举位为牛客多校8.D.OR 二进制+思维_acm竞赛_16牛客多校8.D.OR 二进制+思维_acm竞赛_17,遍历牛客多校8.D.OR 二进制+思维_c++_13牛客多校8.D.OR 二进制+思维_算法_11序列,检验是否成立。如果牛客多校8.D.OR 二进制+思维_acm竞赛_16牛客多校8.D.OR 二进制+思维_acm竞赛_17均不成立,则牛客多校8.D.OR 二进制+思维_数组_05序列无解直接输出牛客多校8.D.OR 二进制+思维_acm竞赛_16​;如果有一个成立,那么对于该位情况唯一,继续枚举;如果全部成立,则对于该位有两种情况,总情况牛客多校8.D.OR 二进制+思维_ios_24

AC Code

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int b[N], c[N];

inline bool check(int k, int x, int n){
for (int i = 1; i < n; i++){
int _or = (b[i] >> k) & 1;
int _and = (c[i] >> k) & 1;
if (_or && !_and) x ^= 1;
if (_or && _and && !x) return false;
if (!_or && _and) return false;
if (!_or && !_and && x) return false;
}
return true;
}

signed main(){
ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n = 0, ans = 1; cin >> n;
for(int i = 1; i < n; i++) cin >> b[i];
for(int i = 1; i < n; i++) cin >> c[i];
for(int i = 1; i < n; i++){
c[i] -= b[i];
if(c[i] < 0) return cout << "0" << endl, 0;
}
for(int i = 0; i < 32; i++){
bool res1 = check(i, 0, n), res2 = check(i, 1, n);
if(!res1 && !res2) return cout << 0 << endl, 0;
else if(res1 && res2) ans *= 2;
else if(res1 || res2) continue;
}
cout << ans << endl;
return 0;
}