链接:https://ac.nowcoder.com/acm/contest/11259/D
来源:牛客网
题目描述
There are two sequences of length n−1n−1, b=(b2,b3,…,bn)b=(b2,b3,…,bn), c=(c2,c3,…,cn)c=(c2,c3,…,cn). Here, each bibi,cici is a non-negative integer.
Now, the sequence a=(a1,a2,…,an)a=(a1,a2,…,an) considers beautiful if and only if forall ii (2≤i≤n)(2≤i≤n), bi=ai−1 or aibi=ai−1orai, ci=ai−1+aici=ai−1+ai and each aiai is a non-negative integer.
Now, Toilet-Ares asks you to calculate the number of beautiful sequences.
输入描述:
The first line contains one integer nn (2≤n≤105)(2≤n≤105) - the length of sequence aa.
The second line contains n−1n−1 integers b2,b3,…,bnb2,b3,…,bn (0≤bi<230)(0≤bi<230) - the elements of sequence bb.
The third line contains n−1n−1 integers c2,c3,…,cnc2,c3,…,cn (0≤ci<231)(0≤ci<231) - the elements of sequence cc.
输出描述:
Print one number - the number of beautiful sequences.
示例1
输入
复制
4
7 5 5
7 9 5
输出
复制
2
做这个题关键就是要知道一个性质(x + y = x & y + x | y)。这样的话(c_i = a_i & a_{i-1} + a_i | a_{i-1}),则设(d_i=c_i-b_i=a_i& a_{i-1}),由此可以知道a数组相邻两个数进行与以及或得到的结果,排除掉了加法产生的进位的影响后,位与位之间就彼此不相关,可以套路地进行按位分析了。如果枚举(a_1)的每一位,根据前面得到的结论实际上就能够唯一确定出(a_2,a_3..a_n)的这一位的值(当然可能不存在),由此也就知道了整个a数组。所以现在要做的就是从高往低或者从低往高枚举(a_1)的每一位,这一位可以为0也可以为1,如果这一位为0成立(即设这一位为0,可以依次得到(a_2,a_3..a_n)的这一位而不引起矛盾)为1也成立,由乘法原理将答案乘2,如果为0为1都不成立则答案为0且终止循环,否则对答案没有贡献,答案不变。
#include <bits/stdc++.h>
using namespace std;
int n, a[100005], b[100005], c[100005], d[100005];
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
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];
}
long long ans = 1;
for(int i = 0; i < 30; i++) {//枚举a[1]的每一位 要么为0要么为1
bool zero = 1, one = 1;
vector<int> v(n + 1);//用来存储a1到an第i位的结果
v[1] = 0;//a1的第i位为0的话
for(int j = 2; j <= n; j++) {//判断是否合法
int nb = (b[j] >> i) & 1, nd = (d[j] >> i) & 1;//获取b数组和d数组第j个元素的第i位
if(nd) {
if(nb) {//aj-1和aj的第i位相与为1 相或也为1
if(v[j - 1]) {//如果aj-1的第i位是1
v[j] = 1;//aj的第i位也是1
} else {//否则根据与或的性质就有矛盾了
zero = 0;
break;
}
} else {//相与为1相或为0,必然不可能
zero = 0;
break;
}
} else {
if(nb) {
if(v[j - 1]) {
v[j] = 0;
} else {
v[j] = 1;
}
} else {
if(v[j - 1]) {
zero = 0;
break;
} else {
v[j] = 0;
}
}
}
}
v[1] = 1;//a1的第i位为1的话
for(int j = 2; j <= n; j++) {
int nb = (b[j] >> i) & 1, nd = (d[j] >> i) & 1;
if(nd) {
if(nb) {
if(v[j - 1]) {
v[j] = 1;
} else {
one = 0;
break;
}
} else {
one = 0;
break;
}
} else {
if(nb) {
if(v[j - 1]) {
v[j] = 0;
} else {
v[j] = 1;
}
} else {
if(v[j - 1]) {
one = 0;
break;
} else {
v[j] = 0;
}
}
}
}
if(zero && one) ans *= 2;
else if(zero ^ one) ans *= 1;
else {
ans = 0;
break;
}
}
cout << ans;
return 0;
}