这道题比赛的时候没做出来,赛后补题的时候发现其实可以构造一个前缀异或和数组,然后根据初始化的第一个值进行填数,但是作为菜鸡的我虽然坚信自己的想法是正确的却想了很久也没有能够构造出来所谓的前缀异或和数组。唉,嘤嘤嘤
本题思路:我们可以根据这个构造一个前缀异或和数组,由ans[ i ] ^ ans[ i - 1 ]就可以得到数组里第i个元素的值。
如何构造这个前缀数组呢,我们暂时把我们构造的前缀数组叫做b,最后输出的答案数组称作a,那么我们可以知道,a [ l ] ^ a[l + 1] ^ .... ^ a[ r ] = b[ r ] ^ b[l - 1]。所以这个问题也就变成了,我们要构造一个
前缀数组,使得任意两个数字的异或和不为x且每次数字只使用一次.(为了避免0的出现),所以我们知道两个异或和为x的数字我们只能选择其中一个。
Can anyone explain me why it's 1 to 2^n - 1?
#include <cstdio> #define len 1 << n #include <vector> #include <algorithm> using namespace std; const int maxn = 1 << 18; int value[maxn]; vector <int> ans; int main() { int n, x; scanf("%d %d", &n, &x); ans.push_back(0); for(int i = 1; i < len; i ++) { if(i != x) { if(value[i]) continue;//只选用未标记的 ans.push_back(i); value[x ^ i] = 1;//不能选择和i异或得到x的数字 } } printf("%d ", ans.size() - 1); for(int i = 1; i < ans.size(); i ++) { if(i > 1) printf(" "); printf("%d", ans[i] ^ ans[i - 1]); } printf(" "); return 0; }