牛客多校8.D.OR 二进制+思维
原创
©著作权归作者所有:来自51CTO博客作者wx58438afac3cd5的原创作品,请联系作者获取转载授权,否则将追究法律责任
Problem Analysis
题目给给定数组各具有个元素,求满足条件的的具有个元素的序列的个数。
拿到题目没啥思路,和队友讨论只需要确定序列的首个元素,后面元素即可唯一确定,发现确实是正确的,但对于首元素的枚举方法如果纯暴力肯定会T,遂向学长求救,得知了神奇的结论:
附赠一个证明过程:
然后通过列真值表,可以证明成立。
那么我们现在可以得出数组(即为),以及(即为),因此我们可以根据这两个数组求:
从最低位开始,每次枚举位为或,遍历和序列,检验是否成立。如果和均不成立,则序列无解直接输出;如果有一个成立,那么对于该位情况唯一,继续枚举;如果全部成立,则对于该位有两种情况,总情况。
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;
}