(与题目中下标不同,这里令下标为$[0,2^{k})$来方便运算)

根据异或的性质,显然有解的必要条件是$\bigoplus_{i=0}^{2^{k}-1}a_{i}=0$

在此基础上,我们考虑构造——

定义$solve(i,j,x)$表示在当前$p_{i}$和$q_{i}$的基础上,构造$p'_{i}$与$q'_{i}$,使得:

1.$\forall 0\le t<2^{k}且t\ne i且t\ne j,p_{t}\oplus q_{t}=p'_{t}\oplus q'_{t}$

2.$p_{i}\oplus q_{i}=p'_{i}\oplus q'_{i}\oplus x$,$p_{j}\oplus q_{j}=p'_{j}\oplus q'_{j}\oplus x$

初始令$\forall 0\le i<2^{k},p_{i}=q_{i}=i$,接下来只需要不断执行$solve(i,i+1,\bigoplus_{j=0}^{i}a_{j})$即可

考虑如何执行$solve(i,j,x)$这个操作,首先若$x=0$直接退出,否则继续分析:

由于都是排列,构造可以通过交换来实现,更具体的来说,我们希望找到$t$,使得$p_{i}$与$p_{t}$交换、$q_{j}$与$q_{t}$交换,使得满足$p_{i}\oplus q_{i}=p'_{i}\oplus q'_{i}\oplus x$(不关心$j$以及其他位置)

上述要求即$p_{t}=p_{i}\oplus x$,根据排列总是存在,然后执行这些交换,对之后的情况分类讨论:

1.$t=j$,那么即已经合法(根据$x\ne 0$,必然有$t\ne i$)

2.$t\ne j$,不难发现交换后不合法的位置仅有$t$和$j$,且我们希望将其异或值异或上$q_{t}\oplus q_{j}\oplus x$,不难发现这就是要求执行$solve(t,j,q_{t}\oplus q_{j}\oplus x)$

重复执行上述递归过程,注意到$j$是不变的,只需要证明$i$不会重复经过一个位置,那么递归次数就是$o(2^{k})$(找到$p_{t}$可以预处理做到$o(1)$),总复杂度即$o(2^{2k})$

下面,我们就要来证明$i$不能重复:

反证法,即假设存在重复,不妨假设是与第一次操作相同(可以将之前与其相同的操作看作第一次),即假设这些递归的$i$依次为$I_{1},I_{2},...,I_{m+1}$,其中$\forall 1\le i<j\le m,I_{i}\ne I_{j}$且$I_{m+1}=I_{1}$

假设递归$I_{1}$时是$solve(I_{1},j,x)$,归纳可得递归$I_{i}$时是$solve(I_{i},j,x\oplus q_{j}\oplus q_{I_{i}})$,接下来考虑递归$I_{m}$时整个序列在递归$I_{1}$前的变化——
$$
\begin{pmatrix}I_{1}&I_{2}&I_{3}&...&I_{m-1}&I_{m}&j\\p_{I_{2}}&p_{I_{3}}&p_{I_{4}}&...&p_{I_{m}}&p_{I_{1}}&p_{j}\\q_{I_{1}}&q_{j}&q_{I_{2}}&...&q_{I_{m-2}}&q_{I_{m-1}}&q_{I_{m}}\end{pmatrix}
$$
(其中第一行为下标,第2行和第3行描述当前的$p$和$q$,这里的$p_{i}$和$q_{i}$都是$I_{1}$操作之前$i$位置的值)

由于是$solve(I_{m},j,x\oplus q_{j}\oplus q_{I_{m}})$,同时由于$I_{m+1}=I_{1}$,即$p_{I_{2}}=p_{I_{1}}\oplus x\oplus q_{j}\oplus q_{I_{m}}$

同时,根据$I_{1}$第1次找到$I_{2}$,有$p_{I_{2}}=p_{I_{1}}\oplus x$,代入后不难得到$q_{j}=q_{I_{m}}$,由于是排列,即$I_{m}=j$,即矛盾

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 5005
4 int n,k,a[N],p[N],q[N],pos[N];
5 void solve(int i,int j,int x){
6 if (!x)return;
7 int t=pos[(p[i]^x)];
8 swap(p[i],p[t]);
9 swap(pos[p[i]],pos[p[t]]);
10 swap(q[j],q[t]);
11 if (t!=j)solve(t,j,(q[t]^q[j]^x));
12 }
13 int main(){
14 scanf("%d",&k);
15 n=(1<<k);
16 for(int i=0;i<n;i++){
17 scanf("%d",&a[i]);
18 if (i)a[i]^=a[i-1];
19 p[i]=q[i]=pos[i]=i;
20 }
21 if (a[n-1]){
22 printf("Fou");
23 return 0;
24 }
25 for(int i=0;i<n;i++)solve(i,i+1,a[i]);
26 printf("Shi\n");
27 for(int i=0;i<n;i++)printf("%d ",p[i]);
28 printf("\n");
29 for(int i=0;i<n;i++)printf("%d ",q[i]);
30 }

[cf1168E]Xor Permutations的更多相关文章

  1. Codeforces Round #440 (Div. 2, based on Technocup 2018 Elimination Round 2) D. Something with XOR Queries

    地址:http://codeforces.com/contest/872/problem/D 题目: D. Something with XOR Queries time limit per test ...

  2. Permutations II

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  3. [LeetCode] Maximum XOR of Two Numbers in an Array 数组中异或值最大的两个数字

    Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...

  4. [LeetCode] Permutations II 全排列之二

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  5. [LeetCode] Permutations 全排列

    Given a collection of numbers, return all possible permutations. For example,[1,2,3] have the follow ...

  6. 二分+DP+Trie HDOJ 5715 XOR 游戏

    题目链接 XOR 游戏 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  7. POJ2369 Permutations(置换的周期)

    链接:http://poj.org/problem?id=2369 Permutations Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

  8. BZOJ 2115 【Wc2011】 Xor

    Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 ...

  9. Permutations

    Permutations Given a collection of distinct numbers, return all possible permutations. For example,[ ...

随机推荐

  1. oracle扩展表空间

    1.  查看表空间的名字及文件所在的位置 select tablespace_name, file_id, file_name, round(bytes / (1024 * 1024), 0) tot ...

  2. 题解 AVL 树

    link Description 给出一个 \(n\) 个点的 AVL 树,求保留 \(k\) 个点使得字典序最小. \(n\le 5\times 10^5\) Solution 因为我很 sb ,所 ...

  3. 关于十二生肖的数学发现(C++)

    把数字看成是年份,然后根据生肖赋值.这里把鼠年赋值为1,牛年赋值为2,虎年赋值为3,兔年赋值为4,龙年赋值为5,蛇年赋值为6,马年赋值为7,羊年赋值为8,猴年赋值为9,鸡年赋值为10,狗年赋值为11, ...

  4. c++中的数学函数

    math.h 数学函数库,一些数学计算的公式的具体实现是放在math.h里,具体有:1 三角函数double sin (double);double cos (double);double tan ( ...

  5. Windows 10下CUDA及cuDNN的安装 —— Pytorch

    Windows 10下CUDA及cuDNN的安装 CUDA简介与下载地址 CUDA(ComputeUnified Device Architecture),是显卡厂商NVIDIA推出的运算平台. CU ...

  6. 使用tinypng对需要上传Gitee图床的图片进行压缩

    目录 背景 Tinypng简介 Tinypng使用 手动上传图片 使用API 调用API自动上传超过1MB图片 安装tinyfy 自动上传脚本 其他 背景 在使用Gitee作为图床时(使用Typora ...

  7. PAT (Basic Level) Practice (中文)1017 A除以B (20分)

    1017 A除以B (20分) 本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数.你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立. 输入格式: 输入在一 ...

  8. Redis 基础数据类型重温

    有一天你突然收到一条线上告警:Redis 内存使用率 85%.你吓坏了赶紧先进行扩容然后再去分析 big key.等你进行完这一系列操作之后老板叫你去复盘,期间你们聊到了业务的数据存储在 Redis ...

  9. 函数返回值为 const 指针、const 引用

    函数返回值为 const 指针,可以使得外部在得到这个指针后,不能修改其指向的内容.返回值为 const 引用同理. class CString { private: char* str; publi ...

  10. vue如何监听数组的变化

    export function def (obj: Object, key: string, val: any, enumerable?: boolean) { Object.defineProper ...