D. Ehab and the Expected XOR Problem(思维)
题目链接:
https://codeforces.com/contest/1174/problem/D
题目大意:
给你n和x,让你构造一个序列使得任何一个连续子序列的异或和不等于0并且不等于x。这个序列中的数的范围是[1,(1<<n)-1],问你最长这个序列为多少,然后输出这个序列。
具体思路:
题解:https://codeforces.com/blog/entry/67388
对于第一个条件,任何一个连续子序列的异或和不等于0,等价于任意两个前缀的异或和不等于0,因为任意两个前缀和能凑出所有的连续子序列。任意两个前缀和的异或和不等于0等价于
任意两个前缀和不存在相等的情况。
对于第二个条件,具体的解题思路和第一个相等。也就是任何一个连续子序列的异或和不等于x,也就是两个前缀的异或和不等于x。
所以,我们可以枚举前缀,每一次判断当前的前缀是否合法就可以了。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 # define inf 0x3f3f3f3f 5 # define ll_inf (1ll<<60) 6 # define lson l,mid,rt<<1 7 # define rson mid+1,r,rt<<1|1 8 const int maxn = 2e6+100; 9 const int N = 15; 10 const int mod = 1e9+7; 11 vector<int>q; 12 map<int,int>vis; 13 int main() 14 { 15 int n,x,maxstate; 16 scanf("%d %d",&n,&x); 17 maxstate=(1<<n)-1; 18 vis[0]=1; 19 int pre=0; 20 for(int i=1; i<=maxstate; i++) 21 { 22 if(vis[i^x]) 23 continue; 24 vis[i]=1; 25 q.push_back(i^pre);// 因为枚举的是前缀,但是这里存储的是当前这个数是多少 26 pre=i; 27 } 28 int len=q.size(); 29 printf("%d\n",len); 30 for(int i=0; i<len; i++) 31 { 32 if(i==0) 33 printf("%d",q[i]); 34 else 35 printf(" %d",q[i]); 36 } 37 printf("\n"); 38 return 0; 39 }