Atcoder AGC031C Differ By 1 Bit (构造、二进制)
哎呀这个C怎么比B还水。。。。(我现在大概也就会做点这种水题了吧)
题目链接
https://atcoder.jp/contests/agc031/tasks/agc031_c
题目大意
符号约定: \(count(x)\)表示整数\(x\)在二进制表示下\(1\)的个数。“二进制表示下第\(x\)位”表示位权为\(2^x\)的位。数组下标全部从0开始
给定\(N,A,B\), 求构造一个\([0,2^N-1]\)的排列\(p\), 满足\(p_0=A, p_{2^N-1}=B\), 对于任何\(i\in[1,2^N-1]\), \(count(p_i\ xor\ p_j)=1\).
\(1\le N\le 17\)
题解
注: 这道题“二进制位相差\(1\)个”的这个条件,我们可以用图形象地表示出来,就是一个\(n\)维立方体顶点和棱的几何结构。这样画出来也许有助于理解本题。
首先观察到一些结论。
(1) 如果一个排列\(p\)是合法的,那么把\(p\)中的每个元素异或一个正整数\(x\)之后得到排列\(p'\),排列\(p'\)仍然是合法的。
太显然,不证了。
据此,我们可以令\(B=B\ xor\ A\), 然后构造一个\(p\)满足\(p_0=0, p_{2^N-1}=B\), 最后把答案序列全部\(xor\ A\)
(2) 能构造出以\(0\)开始以\(B\)结束的合法排列当且仅当\(count(B)\equiv 1(\mod 2)\)
证明: \(|count(p_i)-count(p_{i-1})|=1\), 故\(count(p_{2^N-1})\)为奇数。必要性得证。
充分性?我们可以直接按以下方案进行构造
假设我们要解决问题\((n,b)\) (表示大小为\(n\)起始点为\(0\)终止点为\(b\))
分类讨论\(b\)二进制表示下第\((n-1)\)位
若为\(1\), 则我们先在\([0,2^{n-1}-1]\)内构造一个起始点为\(0\)终止点为\(1\)的排列(递归调用问题\((n-1,1)\)),然后从\(1\)这个点一步跳到\(2^{n-1}+1\), 再构造一个\([2^{n-1},2^n-1]\)的起始点为\(2^{n-1}+1\)终止点为\(b\)的排列。这一部分可以递归调用问题\((n-1,b\ xor\ (2^{n-1}+1))\)然后把生成的排列每个位置都异或\(2^{n-1}+1\)解决。
若为\(0\), 情况稍有复杂。我们依然是构造两个排列,第一个排列\(p_1\)由问题\((n-1,a)\)生成, 而我们希望在排列\(p_1\)中塞入另一个排列,而使得新排列仍然合法。考虑\(p_1[0]\)和\(p_1[1]\) (其中\(p_1[0]\)显然为\(0\)), 构造一个排列\(p_2\)值域为\([2^{n-1},2^n-1]\)且起始于\(2^{n-1}\)终止于\(p_1[1]\ xor\ 2^{n-1}\),这一部分可以通过调用问题\((n-1,p_1[1])\)然后给生成排列的每个元素都加上\(2^{n-1}\)完成。然后我们把\(p_2\)接在\(p_1[0]\)和\(p_1[1]\)之间,它就合法了。
时间复杂度\(T(n)=2T(n-1)+O(2^n)\), 解得\(T(n)=O(2^nn)\)
说了这么多,可能不太清楚。。后面我举个例子:(仅展开模拟第一层递归)
例子1: 问题(4,13)的解决
判断出为第一种情况(第3位为1)
首先构造问题(3,1)的排列: 0 4 5 7 6 2 3 1
然后构造问题(3,4)的排列: 0 2 3 1 5 7 6 4,其中4=13 xor 9, 9=2^3+1
问题(3,4)的排列每个数xor 9之后可得: 9 11 10 8 12 14 15 13
前后拼接即可得: 0 4 5 7 6 2 3 1 9 11 10 8 12 14 15 13就是答案
例子2: 问题(4,7)的解决
判断出为第二种情况(第3位为0)
首先构造问题(3,7)的排列p1: 0 2 3 1 5 4 6 7, 发现p1[1]是2
然后构造问题(3,2)的排列: 0 4 6 7 5 1 3 2, 然后每个数+8后可得8 12 14 15 13 9 11 10
然后把这个以8开头以10结束的排列插在p1的0和2之间,得到0 8 12 14 15 13 9 11 10 2 3 1 5 4 6 7就是答案
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int N = 17;
int ans[(1<<N)+3];
int cnt[(1<<N)+3];
int tmp[(1<<N)+3];
int n,A,B;
void solve(int x,int a,int ret[])
{
if(x==0) {ret[0] = 0; return;}
if(x==1) {ret[0] = 0; ret[1] = 1; return;}
if(a&(1<<(x-1)))
{
solve(x-1,1,ret);
solve(x-1,a^((1<<(x-1))+1),ret+(1<<(x-1)));
for(int i=(1<<(x-1)); i<(1<<x); i++) ret[i] = ret[i]^((1<<(x-1))+1);
}
else
{
solve(x-1,a,ret);
solve(x-1,ret[1],ret+(1<<(x-1)));
for(int i=(1<<(x-1)); i<(1<<x); i++) ret[i] = ret[i]^(1<<(x-1));
tmp[0] = ret[0]; for(int i=0; i<(1<<(x-1)); i++) tmp[i+1] = ret[i+(1<<(x-1))];
for(int i=((1<<(x-1))+1); i<(1<<x); i++) tmp[i] = ret[i-(1<<(x-1))];
for(int i=0; i<(1<<x); i++) ret[i] = tmp[i];
}
}
int main()
{
scanf("%d%d%d",&n,&A,&B); B^=A;
for(int i=1; i<(1<<n); i++) cnt[i] = cnt[i>>1]+(i&1);
if((cnt[B]&1)==0) {puts("NO"); return 0;}
puts("YES");
solve(n,B,ans);
for(int i=0; i<(1<<n); i++) ans[i]^=A;
for(int i=0; i<(1<<n); i++) printf("%d ",ans[i]);
return 0;
}
Atcoder AGC031C Differ By 1 Bit (构造、二进制)的更多相关文章
- 2018.09.22 atcoder Integers on a Tree(构造)
传送门 先考虑什么时候不合法. 第一是考虑任意两个特殊点的权值的奇偶性是否满足条件. 第二是考虑每个点的取值范围是否合法. 如果上述条件都满足的话就可以随便构造出一组解. 代码: #include&l ...
- Atcoder beginner contest 249 C-Just K(二进制枚举)
题目大意:给你N个字符串,你可以从中选择任意数量的字符串,请统计在你的字串中,相同字母出现次数正好为K次的字母数.数据保证出现的字母都是小写字母. 1≤N≤15 1 ≤K≤N 一开始读题的时候读错了, ...
- 【译】构造和匹配二进制(Efficiency Guide)
可以通过以下方式有效地构建二进制: my_list_to_binary(List) -> my_list_to_binary(List, <<>>). my_list ...
- Java 构造 BSON 数据类型
Java 构造 BSON 数据类型 整数/符浮点数 Java BSON 构造整数/符浮点数类型 // {a:123, b:3.14} BSONObject obj = new BasicBSONObj ...
- 转载:【原译】Erlang构建和匹配二进制数据(Efficiency Guide)
转自:http://www.cnblogs.com/futuredo/archive/2012/10/19/2727204.html Constructing and matching binarie ...
- Erlang 位串和二进制数据
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=25876834&id=3300393 因为在本人工作中,服务端Erla ...
- Java API 快速速查宝典
Java API 快速速查宝典 作者:明日科技,陈丹丹,李银龙,王国辉 著 出版社:人民邮电出版社 出版时间:2012年5月 Java编程的最基本要素是方法.属性和事件,掌握这些要素,就掌握了解决实际 ...
- C#功能扩张方式
有时候,为了完成一些window的一些操作,需要引入一些dll进行操作 1) 引入系统api进行操作,形如[DllImport("urlmon.dll", CharSet = C ...
- 【学习笔记】tensorflow图片读取
目录 图像基本概念 图像基本操作 图像基本操作API 图像读取API 狗图片读取 CIFAR-10二进制数据读取 TFRecords TFRecords存储 TFRecords读取方法 图像基本概念 ...
随机推荐
- mac下安装tensorflow及入门例子
https://www.tensorflow.org/install/install_mac 使用virtualenv安装,virtualenv相当于使tensorflow运行在虚拟机环境下. 需要使 ...
- EF + WCF学习笔记——EF实体类序列化
项目中如果 EF + WCF 结合使用,模式应该是EF负责读取数据库,传递数据对象给WCF,WCF再将这些对象传送给客户端.因为WCF传送的对象需要序列化,而EF默认生成的对象并没有序列化,很可能会出 ...
- HDU3183 RMQ/贪心
A Magic Lamp Problem Description Kiki likes traveling. One day she finds a magic lamp, unfortunately ...
- [RK3288][Android6.0] U-boot 启动流程小结【转】
本文转载自:http://blog.csdn.net/kris_fei/article/details/52536093 Platform: RK3288OS: Android 6.0Version: ...
- EMC 存储管理
第一章EMC 产品介绍 1.1. 名词介绍 DAE——磁盘笼.用于装载磁盘的柜子. ◆Disk processor enclosure——含磁盘的控制器单元.存储系统的主要设备,内含存 ...
- [BZOJ 1718] Redundant Paths
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1718 [算法] 用Tarjan算法找出所有e-DCC(边-双联通分量),然后将这张图 ...
- 第2章 安装Nodejs 2-3 Windows下安装Nodejs
http://nodejs.org
- 洛谷P1040 加分二叉树(区间dp)
P1040 加分二叉树 题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di, ...
- 网络简要<入门篇>对应配置代码
交换机的配置 (1)交换机的模式: switch> 用户模式,可以查看设备的部分内容 SW-3ceng>enable SW-3ceng# 进入特权模式,可以查看更多 ...
- [Luogu 2216] [HAOI2007]理想的正方形
[Luogu 2216] [HAOI2007]理想的正方形 题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输 ...