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 }