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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章