Educational Codeforces Round 157 (Rated for Div. 2)(D)拆位

1895D - XOR Construction 

        题意:现有一个长度为n - 1 的a数组,现要求构造出长度为n的b数组,且满足以下条件:

1、b中包含了从0 ~ n - 1 中的所有数,也就是说b是一个排列。

2、b_{i} \oplus b_{i + 1} = a_{i} 对于任意i都成立。

        思路:异或问题想到拆位处理,由于b中包含了0~n-1当中的所有数,换句话说也就是b数组当中每一位上1的数量是已知的。观察式子b_{i} \oplus b_{i + 1} = a_{i} ,两边同时异或b_{i}以后就变成了:b_{i + 1} = a_{i} \oplus b_{i} ,也就是说当 b_{1} 求出来以后,b数组当中其余的数都是固定下来的。因此我们只需要将 b_{1} 中每一位上的数确定下来,整个b数组就能确定下来了。遍历所有位,可以先假设b_{1}当中某一位上的数为0,然后遍历求出整个b数组中该位上1的数量,看是否与之前算出来1的数量相符,如果相符则代表该位可以为0,如果不相符则代表该位上的数字为1。

        

// Problem: D. XOR Construction
// Contest: Codeforces - Educational Codeforces Round 157 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1895/problem/D
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include 
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N=2e05+10;
const LL mod=1e09+7;
typedef pairpl;
priority_queue, greater >t;
priority_queue q;
LL gcd(LL a, LL b){
	return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
	return a / gcd(a , b) * b;
}
int two[N][32];
int cnt[32];
int ans[32];
void solve() 
{
	int n;
	cin>>n;
	int a[n];
	for(int i = 0 ; i < n - 1; i ++)	
		cin>>a[i];
	for(int i = 0 ; i < n - 1 ; i ++){
		for(int j = 0 ; j < 20 ; j  ++){
			if(a[i] >> j & 1){
				two[i][j] = 1;
			}
		}
	}
	for(int i = 0 ; i < n ; i ++){
		for(int j = 0 ; j < 20 ; j ++){
			if(i >> j & 1){
				cnt[j]++;
			}
		}
	}
	for(int i = 0 ; i < 20 ; i ++){
		int last = 0;
		int cnt1 = 0;
		for(int j = 1 ; j < n ; j ++){
			if(two[j - 1][i] == 0){
				if(last)
					cnt1++;
			}
			else{
				last = last? 0 : 1;
				if(last == 1)
					cnt1++;
			}
		}
		if(cnt1 == cnt[i]){
			ans[i] = 0;
		}
		else{
			ans[i] = 1;
		}
	}
	int st = 0;
	for(int i = 0 ; i < 20 ; i ++){
		if(ans[i]){
			st += 1 << i;
		}
	}
	cout<>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

你可能感兴趣的:(算法,数据结构)