uva 12486-Space Elevator

//http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3930

//Problem description:

Space Elevator

China is building a space elevator, which will allow the launching probes and satellites to a much
lower cost, enabling not only scientific research projects but also space tourism.
However, the Chinese are very superstitious, and therefore have a very especial care with the
numbering of floors in the elevator: they do not use any number containing the digit “4” or the
sequence of digits “13”. Thus, they do not use the fourth floor or the floor 13 or the floor 134 nor the
floor 113, but use the floor 103. Thus, the first floors are numbered 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 15,
16, . . .
As the space elevator has many levels, and levels must be numbered, the Chinese asked you to
write a program that, given the level, indicates which number should be assigned to it.


Input

The input contains several test cases. Each test case consists of a single line containing an integer
N which indicates the floor whose number should be determined.


Output

For each test case, print a line containing a single integer indicating the number assigned to the
N-th floor.
Restrictions

• 1 ≤ N ≤ 10^18


Examples
Sample input
1
4
11
12
440
Sample output
1
5
12
15

666

//解题思路:一个数位dp的题,dp[i][0]记录不含4和13且第一位数字不为3的个数,dp[i][1]记录不含4和13但第一位数字为3的个数,dp[i][2]记录里面含有4或13,或都有的个数,最后状态转移如下所示:


dp[i][0]=7*(dp[i-1][0]+dp[i-1][1])+dp[i-1][0];
dp[i][1]=dp[i-1][0]+dp[i-1][1];
dp[i][2]=dp[i-1][1]*2+dp[i-1][0]+10*dp[i-1][2];
这题还有一个注意的地方就是long long 的范围不够用了,要用unsigned long long; 


//Code as follows:

#include<stdio.h>
#include<string.h>
unsigned long long dp[22][3],num[22];
void init()
{
	int i;
	memset(dp,0,sizeof(dp));
	dp[0][0]=1;
	for(i=1;i<20;i++)
	{
		dp[i][0]=7*(dp[i-1][0]+dp[i-1][1])+dp[i-1][0];
		dp[i][1]=dp[i-1][0]+dp[i-1][1];
		dp[i][2]=dp[i-1][1]*2+dp[i-1][0]+10*dp[i-1][2];
	}
	num[0]=1;
	for(i=1;i<20;i++)
		num[i]=num[i-1]*10;
}

unsigned long long get(unsigned long long n)
{
	int i,flag=0;
	unsigned long long p[22],pnum[22],sum=0;
	memset(pnum,0,sizeof(pnum));
	i=0;
	while(n)
	{
		p[++i]=n%10;
		pnum[i]=pnum[i-1]+num[i-1]*p[i];
		n/=10;
	}
	for(;i;i--)
	{
		sum+=dp[i-1][2]*p[i];
		if(p[i]==1)
			flag=1;
		else if(p[i]>1)
		{
			if(i>1)
				sum+=dp[i-1][1];
			if(p[i]==3)
			{
				if(flag)
				{
					sum+=pnum[i-1]+1;
					break;
				}
			}
			else if(p[i]>3)
			{
				if(flag)sum+=dp[i][1];
				if(p[i]==4)
				{
					sum+=pnum[i-1]+1;
					break;
				}
				else 
				{
					sum+=dp[i-1][1];
					sum+=dp[i-1][0];
				}
			}
			flag=0;
		}
		else flag=0;		
	}
	return sum;
}
unsigned long long find(unsigned long long n)
{
	unsigned long long tem,mid,start=0,end=num[19]+1,t;
	while(start<=end)
	{
		t=start%2+end%2;
		mid=start/2+end/2+t/2;
		tem=mid-get(mid);
		if(end==mid)break;
		if(tem>=n)
			end=mid;
		else start=mid+1;
	}
	return end;
} 
int main()
{
	unsigned long long n;
	//freopen("out.out","w",stdout);
	init();
	while(scanf("%llu",&n)!=EOF)
		printf("%llu\n",find(n));
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值