B. Curiosity Has No Limits【思维 规律】

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;
} 

猜你喜欢

转载自blog.csdn.net/liangnimahanwei/article/details/83244363