Codeforces- 1547D-Co-growing Sequence

Codeforces- 1547D-Co-growing Sequence

题目大意:

​ 又是一道位运算啊,为什么位运算的题目都是酱紫绕来绕去的?这题是这样的:

​ 对长度为n的数组a,满足a[i] = a[i] & a[i - 1],即后一个和当前的与等于当前,就称a数组“grow”。

​ 对两个长度为n的数组a、b,每一位两两亦或得到新的数组c,若数组c是“grow”的那就称a、b是“co-grow”的。

​ 现给你一个a数组,请求出字典序最小的b数组。

思路:

​ 要字典序最小,b的第一个元素一定是0。a数组是确定的,而b[0]是确定的0,所以c[0]是确定的,即b[0]^0 = b[0]。ok,有了第一个c,我们就可以开始贪了:)。

​ 对于每一个c[i-1],他的二进制位j若是1,那c[i]的对应j位也一定要是1 。(因为要满足c的“grow”要求)。

cij= 1的话,就要看已经确定了的a来判断bij 。而若c[i-1][j]为0的话,cij可0可1,对应的bij直接置0即可。

代码实现:

#include<bits/stdc++.h>
#define debug cout<<"= =\n"
#define pii pair< int , int >
#define pll pair< long long , long long >

/*
=========> A Tyrion Project . 
*/

using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f;
const ll N = 2*1e6+1000;
const ll mod = 1e9 + 7 ;

/////////////////////////////////////////////////

int n , tmp ;
vector<bitset<30> >a , b , c ;

void solve(){
	
	int n , a , b , c ;
	cin>>n>>c ;
	cout<<"0 " ;
	
	for(int i = 2 ; i <= n ; i ++ ){
		cin>>a ; b = 0 ;
		
		for(int j = 0 ; j < 30 ; j ++ ){
			int posa = a & (1 << j) ;
			int posc = c & (1 << j) ;
			
			if(posc && !posa)b += (1 <<j) ;
			
		}
		cout<<b<<" " ;
		c = a ^ b ;
	}
	cout<<"\n" ;

}

int main(){
	
	ios::sync_with_stdio(false) ;
	//freopen("inn.in","r",stdin) ;
	ll T ;
	cin>>T ;
	while(T -- )solve() ;
		
}

写在后面:

​ 一开始想用bitset做的,然后发现用bitset还要把二进制转回来好麻烦,就用上述代码中的方式来遍历二进制的每一位。

posted @ 2021-09-30 17:41  tyrii  阅读(65)  评论(0)    收藏  举报