题意:两个整数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]) ;
}