京东2017届毕业生校园招聘笔试题《第K个幸运数字》
考题回忆如下:
所谓幸运数字就是每一位的数字除了4就是7,例如4,7,44,47,74,77,444,447,474,477,744,747,774,777....。第K个幸运数字就是,就是所有幸运数字从小到大排列,第1个为4,第2个为7,第3个为44,第4个为47,第5个为74.......
输入第一行为求幸运数字的个数T(1≤T≤1000),之后每行是要求的第K个幸运数字(1≤K≤1018)
例如:
本地输入: 3 5 100 1000000000 输出: 74 744747 77477744774747744747444444447本人的代码如下(仅代表个人观点,并不代表最优):
#include<iostream> #include<math.h> #include<list> using namespace std; void PrintNum(list<int> Lis,int cnt) { while (Lis.size()<cnt--) { cout<<4; } for(list<int>::iterator itr=Lis.begin();itr!=Lis.end();++itr) { if(*itr==0) cout<<4; else cout<<7; } cout<<endl; } list<int> BinaryVector(long long n) { long long temp; temp = n; list <int> L; while(0 != temp) { L.push_front(temp % 2); temp = temp >> 1; } return L; } int main() { int T; cin>>T; long long *K=new long long[T]; for(int i=0;i<T;++i) { cin>>K[i]; } for(int i=0;i<T;++i) { long long temp=0; int j=0; while (temp<=K[i]) { ++j; temp=pow(2,j); } if(pow(2,j)==K[i]+1) { temp=K[i]+2-pow(2,j); list<int> Lis=BinaryVector(temp-1); PrintNum(Lis,j); }else { temp=K[i]+2-pow(2,j-1); list<int> Lis=BinaryVector(temp-1); PrintNum(Lis,j-1); } } delete K; system("PAUSE"); return 0; }
解题思路:
先观察幸运数字:4,7,44,47,74,77,444,447,474,477,744,747,774,777....
不难得出如下两个结论:1.n位幸运数字的个数是2n个。假设第K个幸运数字是由n位数字组成,则可将K分成两部分,前n-1位数字总数
2
1
+
2
2
+
2
3
+...+.
2
n-2
+
2
n-1
与
K-(
2
1
+
2
2
+
2
3
+....+
2
n-2
+
2
n-1
)的和,所以第K个幸运数字就是n位数字中的第K-(
2
1
+
2
2
+
2
3
+....+
2
n-2
+
2
n-1
)个,这样分的好处可以从结论2发现;
2.每位数字除了4就是7,相当于只有4和7的二进制,可以把它转换成0/1表示的二进制,所以幸运数字
4,7,44,47,74,77,444,447,474,477,744,747,774,777....就是0,1,00,01,10,11,000,001,010,011,100,101,110,111.....结合结论1这个题进一步的转换成n位二进制第
K-(
2
1
+
2
2
+
2
3
+....+
2
n-2
+
2
n-1
)个二进制数是多少?可以首先判断有多少位,然后再判断第几个。
例如:第5个幸运数字是由两位数字组成,5是由两位幸运数字组成的第5
-
2
1
=3个,即00,01,10,11的第3个10,转换由7和4组成幸运数字就是74。
注意事项: 1.K的范围是1~1018,所以不要用累加的方法求幂运算,否则会超时,解决方法有两个,一个事用数***算库math.h中的幂运算函数double pow(int,int),或者用位运算右移。
2.高位为0的时候,没有补零会造成输出结果错误,如两位数、三位数的第3个幸运数字不补零都是74,而三位数应该是474
3.2
1
+
2
2
+
2
3
+....+
2
n-2
+
2
n-1=2n-2
#京东#