京东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
#京东#
查看6道真题和解析
海康威视公司福利 1409人发布