复赛一:格雷码(grad code)

洛谷:5657
OJ: CSPS2019A

每一个阶段

前半段或后半段二分次数对应的位数是0还是1

取决于上一个阶段

也就是看k在上一个阶段
是在前半段
还是后半段

来自前半段的话

  • 前半段对应位数的字符则是0
  • 后半段是1

来自后半段的话

  • 前半段对应位数的字符则是1
  • 后半段是0

可以在处理的过程中直接输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**************************************************************** 
 * Description: 2019_S_semi_1  格雷码
 * Author: Alex Li
 * Date: 2024-09-21 10:25:29
 * LastEditTime: 2024-09-22 05:42:46
****************************************************************/
#include <cstdio>
#include <iostream>
#include <cmath>

using namespace std;

unsigned long long k,bk;
int n;
bool flag=0;  //flag为0,表示序列在前半段,第一个数是0,后半段第一个数是1
  
int main(){
  
	cin>>n>>k;
	bk=pow(2,n-1);//从0开始编号则n-1
  
	while(bk){ //直到长度为0
    
		if(!flag){
			if(k < bk) cout<<0;//此处省略一个flag=false;
			else if(k >= bk) {
				cout<<1;
				k -= bk;//为下一阶段判断k的位置做准备
				flag = true;//k在后半段下一阶段为10顺序
           
			}
		}
        
		else if(flag){
		   if(k < bk){
		    	cout<<1;
		    	flag = false;//若k在前半段,使下一阶段为01顺序
			} 
			else if(k >= bk) { //如果k大于bk则在后半段
				cout<<0;
				k -= bk;//为下一阶段判断k的位置做准备
                                        //此处省略一个flag=true;
			}
		}
        
		bk >>= 1;//每次去掉一半,k在前半段则去掉后半段长度,在后半段则去掉前半段长度
        
        
	}
  
	return 0;
}
Scroll to Top