本文将同步发布于:

题目

题目链接:洛谷 AT4693AtCoder agc031_c

题意概述

给定三个数 \(n,a,b\),求一个 \(0\sim 2^n-1\) 的排列满足下列三个条件:

  • \(p_1=a\);
  • \(p_{2^n}=b\);
  • \(\operatorname{popcount}(p_i\oplus p_{i+1})=1\),其中 \(\oplus\) 表示按位异或。

请你判定是否可以构造并输出方案(若可以)。

题解

启发式的画图

直接考虑这个问题,似乎有些困难?

我们先用简单的语言,将它转化为一个图论问题。

图论转化

如果两个整数 \(a,b\in[0,2^n)\),满足 \(\operatorname{popcount}(a\oplus b)=1\),那么我们就在 \(a,b\) 之间连一条边。

那么问题转化为了给定起点与终点,求一条长度为 \(2^n\) 的简单路径。


转化成了图论问题,我们肯定要用几何直观来看看这个图到底是什么样子,采用画图工具 Graph Editor,取 \(n=2,3\) 时:

图片 \(n=2\):

图片 \(n=3\):

这提醒我们,整个图将会形成一个 \(n\) 维立方体。

具体地,我们考虑证明这件事,非常简单,换个角度即可。我们将一个二进制数各位上的数分开,看作各个维度的坐标值,例如 \(0=(00)_2\to (0,0),2=(10)_2\to (1,0)\)。那么我们不难得到此结论。

熟练解决图论问题

我们不难发现,这个图是一个二分图,其中左部点编号对应的二进制数中 \(1\) 的个数为偶数,右部点编号对应的二进制数中 \(1\) 的个数为奇数。

我们由此得到结论,如果存在答案,那么 \(\operatorname{popcount}(a\oplus b)\equiv 1\pmod 2\)。

这个条件对解的必要性已经得到证明,下面我们通过构造来证明其充分性。

构造与递推

首先为了化简问题,我们不难发现从 \(a\) 走到 \(b\) 等价于从 \(0\) 走到 \(a\oplus b\),这是因为异或的自反律与交换律,即 \(p_i\oplus x\oplus p_{i+1}\oplus x=p_i\oplus p_{i+1}\)。

对于 \(n\) 维立方体,它一定是由两个 \(n-1\) 维立方体上下拼接而成。

因此,我们考虑用类似数学归纳法的方式进行构造。

我们具有归纳基础,因为显然我们会 \(n=1\) 时的情况(一条线段从 \(0\) 走到 \(1\));

我们考虑如何通过 \(n-1\) 维的方案构造 \(n\) 维的方案,我们决定分类讨论:

  • 根据上面的理论,我们分类讨论终点的位置(起点为 \(0\));
  • 终点 \(t\) 与起点在不同的层:我们找到一条合法的从起点走 \(n-1\) 维空间到达 \(x\) 的方案,然后 \(x\) 走到另一层对应的点 \(x'\),再在 \(n-1\) 维空间中从 \(0\) 走到 \(t\oplus x'\) 的方案,\(x\) 可任取;
  • 终点 \(t\) 与起点在同一层:我们直接从 \(0\) 走到 \(t\),然后把路径从路径中任意两个相邻点之间直接分割开来,在中间插入一个下层的 \(n-1\) 维的路径。

上面的文字叙述可能有点难懂,我们画个三维空间的图:

第一种情况:

第二种情况:

至此,我们用构造的方法证明了条件的充分性,可解决本题。

时间复杂度为 \(T(n)=2T(n-1)+\Theta(2^n)\),分析可知为 \(\Theta(2^nn)\)。

参考程序

参考程序中情况一选取 \(x=1\),情况二选取起点和路径的第二个点。

__builtin_parity(x) 表示求 \(x\) 的二进制表示中 \(1\) 的个数的奇偶性,奇数为 \(1\),偶数为 \(0\)。

#include<bits/stdc++.h>
using namespace std;
#define reg register
typedef long long ll;
#define flush() (fwrite(wbuf,1,wp1,stdout),wp1=0)
#define putchar(c) (wp1==wp2&&(flush(),0),wbuf[wp1++]=c)
static char wbuf[1<<21];int wp1;const int wp2=1<<21; inline void write(reg int x){
static char buf[32];
reg int p=-1;
if(!x) putchar('0');
else while(x) buf[++p]=(x%10)^'0',x/=10;
while(~p) putchar(buf[p--]);
return;
} inline void writeln(const char *s){
while(*s) putchar(*(s++));
putchar('\n');
return;
} const int MAXN=17; inline void solve(reg int x,reg int a,reg int ans[]){
if(!x)
ans[0]=0;
else if(x==1)
ans[0]=0,ans[1]=1;
else{
reg int val=1<<(x-1);
if(a&val){
solve(x-1,1,ans),solve(x-1,a^(val+1),ans+val);
for(reg int i=val;i<(1<<x);++i)
ans[i]=ans[i]^(val+1);
}
else{
solve(x-1,a,ans),solve(x-1,ans[1],ans+val);
for(reg int i=val;i<(1<<x);++i)
ans[i]=ans[i]^val;
static int tmp[1<<MAXN];
tmp[0]=ans[0];
for(reg int i=0;i<val;++i)
tmp[i+1]=ans[i+val];
for(reg int i=val+1;i<(1<<x);++i)
tmp[i]=ans[i-val];
for(reg int i=0;i<(1<<x);++i)
ans[i]=tmp[i];
}
}
return;
} int n,A,B;
int ans[1<<MAXN]; int main(void){
scanf("%d%d%d",&n,&A,&B);
B^=A;
if(__builtin_parity(B)){
writeln("YES");
solve(n,B,ans);
reg int U=(1<<n)-1;
for(reg int i=0;i<=U;++i)
write(ans[i]^A),putchar(i==U?'\n':' ');
}
else
writeln("NO");
flush();
return 0;
}

「题解」agc031_c Differ by 1 Bit的更多相关文章

  1. 「题解」「美团 CodeM 资格赛」跳格子

    目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...

  2. 「题解」「HNOI2013」切糕

    文章目录 「题解」「HNOI2013」切糕 题目描述 思路分析及代码 题目分析 题解及代码 「题解」「HNOI2013」切糕 题目描述 点这里 思路分析及代码 题目分析 这道题的题目可以说得上是史上最 ...

  3. 「题解」JOIOI 王国

    「题解」JOIOI 王国 题目描述 考场思考 正解 题目描述 点这里 考场思考 因为时间不太够了,直接一上来就着手暴力.但是本人太菜,居然暴力爆 000 ,然后当场自闭- 一气之下,发现对 60pts ...

  4. 「题解」:[loj2763][JOI2013]现代豪宅

    问题 A: 现代豪宅 时间限制: 1 Sec  内存限制: 256 MB 题面 题目描述 (题目译自 $JOI 2013 Final T3$「現代的な屋敷」) 你在某个很大的豪宅里迷路了.这个豪宅由东 ...

  5. 「题解」:$Six$

    问题 A: Six 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 来写一篇正经的题解. 每一个数对于答案的贡献与数本身无关,只与它包含了哪几个质因数有关. 所以考虑二 ...

  6. 「题解」:$Smooth$

    问题 A: Smooth 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 维护一个队列,开15个指针,对应前15个素数. 对于每一次添加数字,暴扫15个指针,将指针对应 ...

  7. 「题解」:Kill

    问题 A: Kill 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 80%算法 赛时并没有想到正解,而是选择了另一种正确性较对的贪心验证. 对于每一个怪,我们定义它的 ...

  8. 「题解」:y

    问题 B: y 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 考虑双向搜索. 定义$cal_{i,j,k}$表示当前已经搜索状态中是否存在长度为i,终点为j,搜索过边 ...

  9. 「题解」:x

    问题 A: x 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 赛时想到了正解并且对拍了很久.对拍没挂,但是评测姬表示我w0了……一脸懵逼. 不难证明,如果对于两个数字 ...

随机推荐

  1. 利用DNS进行命令控制和搭建隧道

    目录 利用DNS进行命令控制(DNS-Shell) 利用DNS搭建隧道 利用DNS进行命令控制(DNS-Shell) DNS-Shell是一款通过DNS信道实现交互式Shell的强大工具,该工具的服务 ...

  2. 支付宝手机端网页支付 PHP(基于官方提供的demo)

    1.支付宝开放平台添加应用并且签约快捷手机wap支付(应用添加不做详细说明) 2.下载demo,文档中心SDK&Demo, 3.个人中心秘钥管理,查看商户appID,商户私钥,支付宝公钥,商户 ...

  3. Python中Socket编程(TCP、UDP)

    1. TCP协议下的如何解决粘包问题 TCP(transport control protocol 传输控制协议)  使用Nagle算法,将多次间隔较小且数据量小的数据,合并成大的数据块:接受端无法识 ...

  4. 将项目连接到远程仓库git

    方式一: git clone "git中的项目地址",此时会生成一个新的项目2.该步骤用于生成一个本地仓库 将需要提交的所有文件除了node_module.git以及输出文件dis ...

  5. 【BUAA_2020_软工】个人作业

    个人项目作业博客 1. 在文章开头给出教学班级和可克隆的 Github 项目地址(例子如下).(1') 项目 内容 北航2020软工 班级博客 作业要求 具体要求 项目GitHub地址 个人项目 教学 ...

  6. docker 的常见命令行解析

    1.查看本地镜像 sudo docker images 2.查看本地容器 sudo docker ps 3.根据Dockerfile制作镜像命令 sudo docker build -t Myimag ...

  7. [ML] 高德软件的路径规划原理

    路径规划 Dijkstra s:起点:S:已知到起点最短路径的点:U:未知到起点最短路径的点 Step 1:S中只有起点s,从U中找出路径最短的 Step 2:更新U中的顶点和顶点对应的路径 重复St ...

  8. Advanced Archive Password Recovery (ARCHPR) 是一个强大的压缩包密码破解工具,适用于ZIP和RAR档案的高度优化的口令恢复工具。

    RAR压缩文件密码破解工具是一款简单易用的RAR文档和ZIP文档密码破解软件,如果你不小心忘了解压密码或是下载的RAR文件需要密码,那么均可以使用本软件进行暴力破解.不管WinRAR /RAR 的密码 ...

  9. 选择“保留window设置、个人文件及应用”或者“升级安装windows并保留文件设置和应用程序”的 处理干净以后用ghost备份

    个人经验 第一次装好以后 把所有常用软件什么的 还有系统的更新全部装好 删去乱七八糟的临时文件啊什么的 处理干净以后用ghost备份下次需要重装直接从ghost镜像恢复 然后更新软件 打补丁 再备份 ...

  10. Linux软件安装管理之——dpkg与apt-*详解 apt命令(dpkg和apt代替rpm)

    apt list *python* Nosee123关注赞赏支持   Linux软件安装管理之--dpkg与apt-*详解 [Linux软件安装管理系列]- - 传送门: - -<Linux软件 ...