CSP-S Day-1 T1 格雷码

 分治+unsigned long long=AC

传送门(戳这

不开unsigned long long 见祖宗

这道恶心的题这道题我们会发现规律它0~2^(n-1)-1第一位数字为0,后面数字为n-1情况的顺序,而2^(n-1)~2^(n)-1则第一位为1,后面数字为n-1情况的逆序

1 n<=3情况如下n=1: 0 1
2 n=2: 00 01 10 11
3 n=3: 000 001 010 011 111 110 101 100
4 .
5 .
6 .
7 .
8 .

可以看出看出我们的分治(普及-)思想

 1 //不开unsigned long long 见祖宗
 2 #include<iostream>
 3 #include<cstdio>
 4 using namespace std ;
 5 
 6 int n ;
 7 unsigned long long k, sum = 1 ;
 8 
 9 inline unsigned long long kk(int t) {
10     unsigned long long yy = 1 ;
11     for(int i = 1 ;i <= t ;i ++ ) {
12         yy = yy * 2 ;
13     }
14     return yy ;
15 }//定义一个求二的几次方的函数(因为数据小所以不用快速幂)
16 
17 inline void dfs(int m, unsigned long long t, int x) {//m表示还有多少个位置是空的,t为上一次操作之后的数,x表示判断是否逆序
18     if (m == 0) {
19         return ;
20     }//判断边界
21     sum = kk(m-1) ;//求出2的n-1次方
22     if (x == 1) {//判断是否逆序(1为正序)
23         if ( t < sum) {//在前半部分
24             cout << 0 ;//输出0
25             dfs(m-1, t, 1) ;//继续往下搜,下一次仍为顺序
26         }else {
27             cout << 1 ;//在后半部分就输出1
28             dfs(m-1, t-sum, -1) ;//继续搜索且下次逆序
29         }
30     }else {
31         if (t < sum) {//如果逆序且在前半部分(说明要输出后半部分的数)
32             cout << 1 ;//因为逆序所以要反着输出
33             dfs(m-1, t, 1) ;//继续往下搜,因为在前半部分所以下次顺序
34         }else {
35             cout << 0 ;//否则输出0
36             dfs(m-1, t-sum, -1) ;//继续往下搜且逆序
37         }
38     }
39 }
40 
41 int main () {
42     cin >> n >> k ;
43     if (k < kk(n-1)) {//对它第一次进行判断(与dfs()里思想一致)
44         cout << 0 ;
45         dfs(n-1, k, 1) ;
46     }else {
47         cout << 1 ;
48         dfs(n-1, k-kk(n-1), -1) ;
49     }
50     cout << “\n” ;
51     return 0 ;//完美结束
52 }

 

这道题巧妙地利用了分治思想

静待各位dalao提出优化(给dalao端茶)

posted @ 2020-02-02 21:14  Tethys  阅读(190)  评论(4编辑  收藏  举报