题目描述
十进制数字中,只含有 6
与 8
的数字被称作幸运数。将所有的幸运数从小到大排序,第一个幸运数是 6,接下来是
8,66,68,86,88, …8,66,68,86,88, …
给定 n,请输出第 n 个幸运数。
输入格式
单个整数:表示 n。
输出格式
单个整数:表示第 n 个幸运数。
数据范围
- 30% 的数据,1≤n≤500
- 60%的数据,1≤n≤1,000,000
- 100%数据,1≤n≤1,000,000,000,000,000
样例数据
输入:7
输出:666
解题思路一
找规律发现,一位有6和8两个数,二位有四个数,三位有8个数,几位数就是2的几次,其实就是n位拆分成前面一位和后面n-1位,每位有两种可能。
把6看成0,8看成1,所有幸运数都利用左移或右移位运算转为二进制数0和1,只需要找出要查找的第n个数在第几层的第几个就能解决该题,注意每层从0开始计数。
先来看如何找到要查找的数在第几层,也就是找出其是几位数:
因为数据规模超出int范围,为防止溢出,数据类型要定义为long long
输入要查找的第n个数,循环每次左移1位判断,m用于记录在第几层,也就是几位数,而n每次减去左移的位数,可以理解为每次剪枝掉前面不需要的幸运数,只保留在当前m层的第几位上,注意是从0计数,最后还需n-1,最终我们得到了要查找的数在第m层的第n个位置。
最后逐个判断每位数,1则输出8,0则输出6:
至于为什么m-1,举例要找的数在第3层的第5位,可理解为下标4的二进制是100,从左往右依次取出每个数&1,右边最后一位从0开始,左边最高位就得m-1,拿出每个数&1,是1输出8,0输出6。
解题思路二
第二种解法是把所有幸运数当作字符串,递归处理。
f(1) = "6"
f(2) = "8"
f(3) = "66" 相当于 f(1) + "6" 奇数 + "6" f( (3-1)/2 ) + "6"
f(4) = "68" 相当于 f(1) + "8" 偶数 + "8" f( (4-1)/2 ) + "8"
f(5) = "86" 相当于 f(2) + "6" 奇数 + "6" f( (5-1)/2 ) + "6"
f(6) = "88" 相当于 f(2) + "8" 偶数 + "8" f( (6-1)/2 ) + "8"
f(7) = "666" 相当于 f(3) + "6" 奇数 + "6" f( (7-1)/2 ) + "6"
递归公式 f( (n-1)/2 ) + (n%2!=0?"6":"8")
递归边界无需考虑0,n==1 "6",n==2 "8"