原题链接(Luogu)
// 就不打freopen了
题目描述
通常,人们习惯将所有 (n) 位二进制串按照字典序排列,例如所有 (2) 位二进制串按字典序从小到大排列为:(00),(01),(10),(11)。
格雷码(Gray Code)是一种特殊的 (n) 位二进制串排列法,它要求相邻的两个二进制串间恰好有一位不同,特别地,第一个串与最后一个串也算作相邻。
所有 (2) 位二进制串按照格雷码排列的一个例子为:(00),(01),(11),(10)。
(n) 位格雷码不止一种,下面给出其中一种格雷码的生成算法:
(1) 位格雷码由两个一位二进制串组成,顺序为:(00),(11)。
(n+1) 位格雷码的前 (2^n) 个二进制串,可以由依此算法生成的 (n) 位格雷码(总共 (2^n) 个 (n) 位二进制串)按顺序排列,再在每个串前加一个前缀 (0) 构成。
(n+1) 位格雷码的后 (2^n) 个二进制串,可以由依此算法生成的 (n) 位格雷码(总共 (2^n) 个 (n) 位二进制串)按逆序排列,再在每个串前加一个前缀 (1) 构成。
综上,(n+1) 位格雷码,由 (n) 位格雷码的 (2^n) 个二进制串按顺序排列再加前缀 (0),和逆序排列再加前缀 (1) 构成,共 (2^{n+1}) 个二进制串。另外,对于 (n) 位格雷码中的 (2^n) 个二进制串,我们按上述算法得到的排列顺序将它们从 (0) ~ (2^n-1) 编号。
按该算法,(2) 位格雷码可以这样推出:
已知 (1) 位格雷码为 (0),(1)。
前两个格雷码为 0 (0),0 (1)。后两个格雷码为 1 (1),1 (0)。合并得到 (00),(01),(11),(10),编号依次为 (0) ~ (3)。
同理,(3) 位格雷码可以这样推出:
已知 (2) 位格雷码为:(00),(01),(11),(10)。
前四个格雷码为:0 (00),0 (01),0 (11),0 (10)。
后四个格雷码为:1 (10),1 (11),1 (101),1 (00)。合并得到:(000),(001),(011),(010),(110),(111),(101),(100),编号依次为 (0) ~ (7)。
现在给出 (n),(k),请你求出按上述算法生成的 (n) 位格雷码中的 (k) 号二进制串。
输入格式
从文件 (code.in) 中读入数据。
仅一行两个整数 (n,k) ,意义见题目描述。
输出格式
输出到文件 (code.out) 中。
仅一行一个 (n) 位二进制串表示答案。
样例
样例 1 输入
1
2 3
样例 1 输出
1
10
样例 1 解释
(2) 位格雷码为:(00),(01),(11),(10),编号从 (0) ~ (3),因此 (3) 号串是 (10)。
样例 2 输入
1
3 5
样例 2 输出
1
111
样例 2 解释
(3) 位格雷码为:(000),(001),(011),(010),(110),(111),(101),(100),编号从 (0) ~ (7),因此 (5) 号串是 (111)。
数据范围
对于 (50\%) 的数据:(n ≤ 10)
对于 (80\%) 的数据:(k ≤ 5 imes 10^6)
对于 (95\%) 的数据:(k ≤ 2 ^ {63}-1)
对于 (100\%) 的数据:(1 le n le 64),(0 le k lt 2^n)
95' 代码
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef unsigned long long llu;
int main(){
freopen("code.in","r",stdin);freopen("code.out","w",stdout);
int n ;
llu k ;
scanf("%d%llu",&n,&k);
k += 1 ;
llu now = pow(2,n);
bool num = 0 ;
// printf("%llu %llu
",now,k);
if(k > now / 2)printf("1");
else printf("0");
if(n > 1){
for(int i = 2 ; i <= n ; i ++){
// printf("
---%d %llu %llu---
",i,now,k);
k %= now ;
if(now > 4){
if(k <= (now / 4) || k > ((3 * now) / 4))printf("0");
else printf("1");
}
else {
if(k <= 1 || k >= 4)printf("0");
else printf("1");
}
now /= 2 ;
}
}
// printf("%llu %llu %d",now, k , n );
return 0 ;
}