异或 前缀和 set

题意:两个整数n和x,求一个最长序列a,使得a的任意一个连续子序列的异或和不为0,且不为x。1<=ai<2^n

题解

1.子序列不容易维护通过异或前缀和转化为单点维护。b序列为a序列的异或前缀和序列。

2.a的任意一个连续子序列的异或和不为0等价于b序列不能有相同的数

3.a的任意一个连续子序列的异或和不为x等价于bi 与 (bi异或x)不能同时存在于b序列中

4.借助set这个容器填充b序列,从1到2^n-1枚举数字向set内填充,若要填充i这个数,则判断set内是否有x异或i这个数字,如果有x异或i这个数字,则不填充i,反之填充i。依据是两个异或得到x的数只能填充一个,并没有先后顺序的特殊性。

题目链接:http://codeforces.com/contest/1174/problem/D

AC代码:

#include<bits/stdc++.h>
#define N 1000005
#define inf 0x3f3f3f3f
using namespace std ;
typedef long long ll ;
set <int> s ;
int num[N] ;
int cnt = 0 ;
int a[N] , b[N] ;
int n , x ;
int main()
{
	int i , j ;
	scanf("%d%d" , &n , &x) ;
	int maxn = (1 << n) ;
	s.insert(0) ;
	for(i = 1 ; i < maxn ; i ++)
	  if(s.find(x ^ i) == s.end())
	  {
	  	s.insert(i) ;
	  	b[++ cnt] = i ;
	  }
	b[0] = 0 ;
	for(i = 1 ; i <= cnt ; i ++)
      a[i] = (b[i] ^ b[i - 1]) ;
	printf("%d\n" , cnt) ;
	for(i = 1 ; i <= cnt ; i ++)
	  printf("%d " , a[i]) ;	 
} 
发布了187 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/95497689