https://codeforc.es/contest/1072/problem/B
题意:给你两个n-1长度的序列 a序列 和 b序列 元素范围是【0,3】
然后是否存在一个 n长度的 t 序列 满足(ti | ti+1 = ai ti & ti+1 = bi)
我在纸写了下情况
一共4*4种情况 当然这存在3 0 和 0 3
排除后有10种 ti ti+1
然后我就发现
如果ai = 0 那bi只能是0
如果ai = 1 那bi可以是0 或 1
如果ai = 2 那bi可以是0 或 2
如果ai = 3 那bi可以是0 或 1 或 2 或 3
然后就看看怎么构成t序列 发现好复杂 设ti ti+1 ti+2 我根据ai可以知道哪些ti ti+1 但是ti可以和ti+1交换 交换了跟ti+2搭配能不能对应上bi+1 ai+1 又是一个新问题 太复杂
现在知道ai bi 能不能得到一些信息
枚举打表 ti ti+1的16的种组合情况 这里注意 0和3 跟 3和0是分开的 不是同一种
把关注点放在a b 因为现在是已知a b
可以发现a = 3 b = 0这种情况有4种 区别在哪里:都是在不同的 t1
a b t1 确定 那t2就是唯一的 那这题a b 全知道 t1确定 怎么弄 :t序列第一个不知道:【0,3】枚举 确定了t2 由于a2 b2知道 不就依次确定了t3 t4 。。。。。
所以可以知道如果t序列的第一个确定了 那后面就是唯一确定的
注意 位运算 加括号 比较好
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1e5 + 100;
int a[maxn], b[maxn], t[maxn];
int main() {
// for (int i = 0; i <= 3; ++i) {
// cout << "t = " << i << "\t\t " << 'a' <<" " << 'b' << endl;
// for (int j = 0; j <= 3; ++j) {
// cout << "t1 = " << i << " " << "t2 = " << j << " " << (i | j) << " " << (i & j) << endl;
// }
// cout << "----------------------------" << endl;
// }
int n;
scanf("%d", &n);
for (int i = 1; i <= n - 1; ++i)
scanf("%d", &a[i]);
for (int i = 1; i <= n - 1; ++i)
scanf("%d", &b[i]);
for (int t1 = 0; t1 <= 3; ++t1) {
int flag = 0;
t[1] = t1;
for (int next = 2; next <= n; ++next) {
for (int tmp = 0; tmp <= 3; ++tmp) {
flag = 0;
if (((t[next - 1] | tmp )== a[next - 1]) && ((t[next - 1] & tmp )== b[next - 1])) {
t[next] = tmp;
flag = 1;
break;//因为唯一确定
}
}
if (!flag) {//无法确定t【next】
break;//说明不行
}
}
if (flag) {//说明t序列已经好了
puts("YES");
for (int i = 1; i <= n; ++i) {
printf("%d ", t[i]);
}
return 0;
}
}
puts("NO");
return 0;
}