D.OR
题目传送门:
题面:
题目大意:
给你n-1个元素的数组
b
,
c
b,c
b,c
b
2
,
b
3
,
b
4
.
.
.
b
n
{b_2,b_3,b_4...b_n}
b2,b3,b4...bn以及
c
2
,
c
3
,
c
4
.
.
.
c
n
{c_2,c_3,c_4...c_n}
c2,c3,c4...cn,
已知
b
i
=
a
i
−
1
∣
a
i
b_i=a_i-_1 | a_i
bi=ai−1∣ai,
c
i
=
a
i
−
1
+
a
i
c_i=a_i-_1+a_i
ci=ai−1+ai。问你能构造出几组这样的数组a?
思路:
所以这样的话相当于相邻a数组的|和&都知道了,避免了进位讨论的麻烦。
这位老哥表格画的特清楚,放着用了。
图源
侵删。
这句话也很关键。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 114514;
ll b[maxn], c[maxn];
int main() {
int n;
cin >> n;
for (int i = 2; i <= n; i++)
cin >> b[i];
for (int i = 2; i <= n; i++) {
cin >> c[i];
c[i] -= b[i];
}
// for (int i = 2; i <= n; i++)
// cout << b[i] << " ";
// cout << endl;
// for (int i = 2; i <= n; i++)
// cout << c[i] << " ";
//cout << endl;
ll ans = 1;
///此时数组b存储的是|,c存储了&;
for (int j = 0; j < 31; j++) {
/// 枚举a1的每一位
int a0 = 1, a1 = 1;
for (int i = 2; i <= n; i++) {
int x = b[i] >> j & 1;
int y = c[i] >> j & 1;
//对b,c当中遍历每一个元素取出第j位
int b0 = 0, b1 = 0;
if (x && y) {
b1 = a1;
//就是全1啦
//保持b0=0;
} else if (x && !y) {
b1 = a0;
b0 = a1;
//就是0和1嘞
} else if (!x && !y) {
b0 = a0;
//保持b1=0;
//就是全0嘞
}
a0 = b0;
a1 = b1;
//确定a[1]这一位的状态
//对取0/1可能性赋值代表前一位对后一位可能的影响。
//只能说很巧妙...
}
ans *= (a0 + a1);
if (!ans) break;
//更新答案
//每一位要么0,1,2三种可能;
// cout << ans << " ";
}
cout << ans << endl;
}