• 2019 CSP-S2 Day1T1题解


    原题链接(Luogu)

    // 就不打freopen了
    

    格雷码(Code)
    输入文件名:code.in
    输出文件名:code.out
    共 20 个测试点,每个测试点 5 分
    每个测试点限时 1 秒,运行内存上限 256MB

    题目描述

    通常,人们习惯将所有 (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 ;
    } 
    
  • 相关阅读:
    推送消息为什么使用RocketMQ,而不使用Kafka?
    com.google.common.collect.Lists.addAll()空指针原因分析
    AQS原理
    ReentrantLock-加锁
    ReentrantLock-自旋
    Reentrantlock-的核心内容
    java中,BigDecimal的add方法避坑指南
    Reentrantlock-实现原理
    Reentrantlock-适用场景
    JAVA foreach和普通for循环是否需要判断为null
  • 原文地址:https://www.cnblogs.com/Shinomiya/p/13888738.html
Copyright © 2020-2023  润新知