【二进制】幸运数字II

幸运数字II
时间限制: 1 Sec 内存限制: 128 MB
题目描述

数字4和7是幸运数字,而其他的都不是幸运数字。一个整数是幸运数字,当且仅当它的十进制表示只包含幸运数字。
现在让你给出第K大(我想说一句,确定不是第K个?)的幸运数字。

输入
第一行一个整数K(1<=K<=1,000,000,000)
输出
第K大的幸运数字。
**样例输入 **
1
样例输出 Copy
4

反正我不是很理解题目所说“第K大”是什么意思,很明显给的样例,4就是第一个幸运数字啊(所有的幸运数字从小到大排列的话),所以就理解第K个幸运数字啦,AC的事实证明就是这样2333.

解题思路:这道题巧妙的运用到了二进制的思维(当你把前几个幸运数字写出来后就会发现了),你会发现,当幸运数字是一位的时候,一共有两个,当位数是2的时候,幸运数字有4个,当位数是3的时候有8个幸运数,可发现幸运数的个数和位数之间是2的幂的关系,而且可以按照二进制的方法 一 一 列出来,就是把4当做二进制中的0,7当做二进制中的1,这样的话正好可以实现从小到大排列,且不重不漏,值得注意的一点是,对于每一位(这里的位指的是这个幸运数有多少位)都要从0开始,解释一下就是,二位数,就以00 为第一个,三位数的话就以000 为第一个,以此类推,如果是八个的话,也就是三位数,二进制表示的十进制要从0开始,也就是以000作为三位数的开端,最大的一个用二进制表示这是111,对应的幸运数字也就是777啦!部分例子已经在代码里注释了,可参考代码;

上代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(int x,int y)//本来一开始用的库函数pow,但是一想还是自己手写一个吧
{
	ll res=1;
	for(int i=0;i<y;i++)
	{
		res*=2;
	}
	return res;
}
ll a[32];
void init()
{
	for(int i=1;i<=35;i++)
	{
		a[i]=qpow(2,i);
	}
} 
int main()
{
	ll k;
	init();
//	for(int i=1;i<=30;i++)
//	{
//		cout<<a[i]<<" ";
//	}
	scanf("%lld",&k);
	if(k==1) cout<<"4";
	else if(k==2) cout<<"7";
	else if(k==3) cout<<"44";
	else{
		int cnt=1;
		for(int i=1;i<=30;i++)
		{
			if(k>=a[i])
			{
				k-=a[i];
			}
			else{
				cnt=i;//表示有几位组成 
				break;
			}
		}
		ll temp=k-1;
		int b[30]={0},s=0;
		while(temp)
		{
			b[s++]=temp%2;
			temp/=2;
		} 
		for(int i=cnt-1;i>=0;i--)
		{
			if(b[i]==1) cout<<"7";
			else cout<<"4";
		}
	}
	return 0;
}
/*
4 7 44 47 74 77 444 447 474 477 744 747 774 777 4444 4447 4474 4477 4744 4774 4777 7444 7447 7474 7744 7747 7774 7777 
0 1 2 3 4
0 1       0 1   2^1
00 01 10 11     0 1 2 3    2^2
000 001 010 011 100 101 110 111   0 1 2 3 4 5 6 7  2^3
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值