题目描述

通常,人们习惯将所有 \(n\) 位二进制串按照字典序排列,例如所有 \(2\) 位二进制串按字典序从小到大排列为:\(00,01,11,10\)。

格雷码(\(Gray Code\))是一种特殊的 \(n\) 位二进制串排列法,它要求相邻的两个二进制串间恰好有一位不同,特别地,第一个串与最后一个串也算作相邻。

所有 \(2\) 位二进制串按格雷码排列的一个例子为:\(00\),\(01\),\(11\),\(10\)。

\(n\) 位格雷码不止一种,下面给出其中一种格雷码的生成算法:

  1. \(1\) 位格雷码由两个 \(1\) 位二进制串组成,顺序为:\(0\),\(1\)。
  2. \(n + 1\) 位格雷码的前 \(2^n\) 个二进制串,可以由依此算法生成的 \(n\) 位格雷码(总共 \(2^n\) 个 \(n\) 位二进制串)按顺序排列,再在每个串前加一个前缀 \(0\) 构成。
  3. \(n + 1\) 位格雷码的后 \(2^n\) 个二进制串,可以由依此算法生成的 \(n\) 位格雷码(总共 \(2^n\) 个 \(n\) 位二进制串)按逆序排列,再在每个串前加一个前缀 \(1\) 构成。

综上,\(n + 1\) 位格雷码,由 \(n\) 位格雷码的 \(2^n\)个二进制串按顺序排列再加前缀 \(0\),和按逆序排列再加前缀 \(1\) 构成,共 \(2^{n+1}\) 个二进制串。另外,对于 \(n\) 位格雷码中的 \(2^n\)个 二进制串,我们按上述算法得到的排列顺序将它们从 \(0 \sim 2^n - 1\) 编号。

按该算法,\(2\)位格雷码可以这样推出:

  1. 已知 \(1\) 位格雷码为 \(0\),\(1\)。
  2. 前两个格雷码为$ 00$,\(01\)。后两个格雷码为 \(11\),\(10\)。合并得到 \(00\),\(01\),\(11\),\(10\),编号依次为 \(0\sim 3\)。

同理,\(3\) 位格雷码可以这样推出:

  1. 已知 \(2\) 位格雷码为:\(00\),\(01\),\(11\),\(10\)。
  2. 前四个格雷码为:\(000\),\(001\),\(011\),\(010\)。后四个格雷码为:\(110\),\(111\),\(101\),\(100\)。合并得到:\(000\),\(001\),\(011\),\(010\),\(110\),\(111\),\(101\),\(100\),编号依次为 \(0\sim7\)。

现在给出 \(n\),\(k\),请你求出按上述算法生成的 \(n\) 位格雷码中的 \(k\) 号二进制串。

输入格式

仅一行两个整数 \(n\),\(k\),意义见题目描述。

输出格式

仅一行一个 \(n\) 位二进制串表示答案。

输入输出样例

输入 #1

2 3

输出 #1

10

输入 #2

3 5

输出 #2

111

输入 #3

44 1145141919810

输出 #3

00011000111111010000001001001000000001100011

说明/提示

【样例 \(1\) 解释】

\(2\) 位格雷码为:\(00\),\(01\),\(11\),\(10\),编号从 \(0\sim3\),因此 \(3\) 号串是 \(10\)。

【样例 \(2\) 解释】

\(3\) 位格雷码为:\(000\),\(001\),\(011\),\(010\),\(110\),\(111\),\(101\),\(100\),编号从 \(0\sim7\),因此 \(5\) 号串是 \(111\)。

【数据范围】

对于 \(50\%\) 的数据:\(n \leq 10\)

对于 \(80\%\) 的数据:\(k \leq 5 \times 10^6\)

对于 \(95\%\) 的数据:\(k \leq 2^{63} - 1\)

对于 \(100\%\) 的数据:\(1 \leq n \leq 64\), \(0 \leq k \lt 2^n\)

这个题正解据说是位运算,但是似乎也不用这么麻烦。然而我考场上并没有开\(unsigned\) \(long\) \(long\)所以我就没了。

考虑按照题意模拟。按照题意,一个\(n\)位的格雷码是由一个前缀\(0\)或\(1\)加上一个长度为\(n-1\)为的格雷码构成的,所以我们可以考虑类似康托展开的方法。

我们不妨先处理出所有\(2\)的幂。对于我们知道这个长度为\(n\)的格雷码在当前所有长度为\(n\)的格雷码中应该正序排第\(k\)位,则如果\(n\lt 2^{n-1}\)(只有小于是因为编号是从\(0\)开始存的)则当前这一位还放\(0\),转移到\(dfs(n-1,k)\);反之放下一个\(1\),考虑怎么处理逆序。

由于我们已经放下了一个\(1\),所以我们已经整个过滤掉了\(2^{n-1}\)个比它排名靠前的格雷码(因为这些格雷码第一位应该是\(0\)),所以我们最后处理编号的范围是\(2^{n-1}\),所以我们首先要把\(k\)减掉\(2^{n-1}\)。手玩一下可以知道,编号从\(0\)开始存这个事情非常麻烦,所以我们需要把这个数整个向右面移一位,也就是加上\(1\)。

再考虑要求倒序排列。这个很简单,因为这\(2^{n-1}\)个格雷码的编号是\(0\sim2^{n-1}-1\),所以容易知道我们只需要用\(2^{n-1}-(k-2^{n-1}+1)\)即可。(其实手玩一下或者打表找规律也行。)

上代码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
#define int long long
#define rep(i,a,n) for(register int i=a;i<=n;++i)
#define dep(i,n,a) for(register int i=n;i>=a;--i)
using namespace std;
int n;
unsigned long long k;
unsigned long long num[64];
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
void write(int x)
{
if(x<0)putchar('-'),x=-x;
if(x==0)return;
write(x/10);
putchar(x%10+'0');
}
void dfs(int step,int k)
{
if(step==0)return;
if(k<num[step-1])
{
putchar('0');
dfs(step-1,k);
}
else
{
putchar('1');
dfs(step-1,num[step-1]-(k-num[step-1]+1));
}
}
signed main()
{
n=read(),k=read();
num[0]=1;
rep(i,1,n-1)num[i]=num[i-1]*2;
dfs(n,k);
return 0;
}

一定注意编号必须从\(0\)存,否则\(unsigned\) \(long\) \(long\)存不下。

2019CSP day1t1 格雷码的更多相关文章

  1. [LeetCode] Gray Code 格雷码

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  2. BZOJ1081[SCOI2005]超级格雷码

    Description 著名的格雷码是指2n个不同n位二进制数(即0~2n-1,不足n位在前补零)的一个排列,这个排列满足相邻的两个二进制数的n位数字中最多只有一个数字不同(例如003和001就有一个 ...

  3. 格雷码原理与Verilog实现

    格雷码原理 格雷码是一个叫弗兰克*格雷的人在1953年发明的,最初用于通信.格雷码是一种循环二进制码或者叫作反射二进制码.格雷码的特点是从一个数变为相邻的一个数时,只有一个数据位发生跳变,由于这种特点 ...

  4. FPGA学习笔记之格雷码、边沿检测、门控时钟

    一.格雷码 格雷码的优点主要是进位时只有一位跳变,误码率低. 1.二进制转格雷码 我们观察下表: 二进制码 格雷码 00 00 01 01 10 11 11 10 二进制码表示为B[],格雷码表示为G ...

  5. LeetCode:Gray Code(格雷码)

    题目链接 The gray code is a binary numeral system where two successive values differ in only one bit. Gi ...

  6. c++实现gray code(格雷码)

    今天别人问的一道题,强调用分治法实现 =.= 百度了一下格雷码,然后写了一下. 关于格雷码大家看百度的吧,特别详细,贴个图: 代码如下(header_file.h是我自己写的一个头文件,包括常见的ve ...

  7. 产生n位元的所有格雷码

    原文链接:http://blog.csdn.net/beiyeqingteng/article/details/7044471 问题:产生n位元的所有格雷码. 格雷码(Gray Code)是一个数列集 ...

  8. Gray code---hdu5375(格雷码与二进制码,普通dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5375 题意就是:给你一串二进制码,里面可能含有'?'这个既可以表示0又可以表示1, 让我们把这个二进制 ...

  9. HDU 5375 Gray code 格雷码(水题)

    题意:给一个二进制数(包含3种符号:'0'  '1'  '?'  ,问号可随意 ),要求将其转成格雷码,给一个序列a,若转成的格雷码第i位为1,则得分+a[i].求填充问号使得得分最多. 思路:如果了 ...

随机推荐

  1. Jenkins构建Jmeter项目之源代码管理(SVN)

    1.查看项目创建中是否又svn插件,没有的话下载插件subversion 2.配置svn源代码管理,如下图(testcases目录下包含build.xml和脚本文件) 3.查看Jenkins本地工作空 ...

  2. 简单了解工作空间工厂(IWorkspaceFactory)

    工作空间工厂(WorkspaceFactory)是工作空间的发布者,允许客户连接通过一组连接属性定义的工作空间. 工作空间表达了一个包含一个或多个数据集的数据库或数据源,数据集可以是表.特征类.关系类 ...

  3. Bran的内核开发教程(bkerndev)-02 准备工作

    准备工作   内核开发是编写代码以及调试各种系统组件的漫长过程.一开始这似乎是一个让人畏惧的任务,但是并不需要大量的工具集来编写自己的内核.这个内核开发教程主要涉及使用GRUB将内核加载到内存中.GR ...

  4. Linux系统基础

    Linux系统基础 目录   简介 0x01 Linux文件与目录管理 0x02 Linux系统用户以及用户组管理 0x03文档的压缩与打包 0x04 apt安装软件 0x05 进程管理 标签 Lin ...

  5. 去除提示“Chrome正在受到自动软件的控制”

    现象:用selenium启动浏览器出现‘Chrome正在受到自动软件的控制’ 解决办法:在启动浏览器前加上如下配置 # 加启动配置 option = webdriver.ChromeOptions() ...

  6. 微信分享—ios和安卓机制居然不一样!

     实际项目中,在做微信分享追踪的时候,遇到了一个百思不得其解的问题. 在加入了用户分享追踪功能之后,页面已经加载完成的情况下,安卓分享功能没有任何问题,ios却总是分享失败. 关于ios和安卓设备的差 ...

  7. Arduino学习笔记③ 经典LED

    1.前言     今天我们开始同时讲解理论以及实践.对于绝大部分有过单片机编程经历的人来说,第一个接触的大多数就是LED灯(忽然想起博主大一那个懵懂的时代,当时大三的师兄给我们展现了一把流水灯功力,当 ...

  8. 百万年薪python之路 -- 异常处理

    异常处理 1.错误的分类: 1.语法错误:(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法错误示范二 def test: pass #语法错 ...

  9. Veins(车载通信仿真框架)入门教程(二)——调用第三方库

    Veins(车载通信仿真框架)入门教程(二)——调用第三方库 在借助Veins进行自己的研究时我们经常需要实现一些比较复杂的功能,有时就需要借助第三方库的帮助. 博主的研究需要使用神经网络,但是自己编 ...

  10. unity image 设置图片

    从任意文件目录下读取文件并在unity中显示: 1)读取目标文件 byte[] imageByte = File.ReadAllBytes(imagePath); 2)转换成纹理 texture.Lo ...