hihoCoder #1301 : 筑地市场 (打表+构造)

题目大意:问含有4或者7的第k大的正数是多少。

题目分析:1~10、1~100、1~1000...之间的含有4或者7的个数可以求出,这样就可以从高位到地位依次确定这个数的每一位上的值。


代码如下:
# include<iostream>
# include<cstdio>
using namespace std;
# define LL long long
# define uLL unsigned long long

uLL a[20]={2,36,488,5904,67232,737856,7902848,
83222784,865782272,8926258176,91410065408,
931280523264,9450244186112,95601953488896,
964815627911168,9718525023289344,
97748200186314752,981985601490518016
};

uLL b[20][10];

uLL n;

void init()
{
	for(int i=0;i<10;++i){
		if(i==4||i==7) b[0][i]=10;
		else b[0][i]=2;
	}
	for(int i=1;i<18;++i){
		for(int j=0;j<10;++j){
			if(j==4||j==7)
				b[i][j]=b[i-1][j]*10;
			else
				b[i][j]=a[i];
		}
	}
}

int main()
{
	init();
	cin>>n;
	uLL ans=0;
	int cnt=0;
	while(n>0){
		if(n<=2){
			if(n==1) ans+=4;
			else ans+=7;
			break;
		}
		int k=17;
		while(k>=0&&n<=a[k])
			--k;
		cnt=0;
		while(cnt<10&&n>b[k][cnt]){
			n-=b[k][cnt];
			++cnt;
		}
		uLL res=cnt;
		for(int i=0;i<=k;++i)
			res*=10;
		ans+=res;
		if(cnt==4||cnt==7){
			ans+=n-1;
			break;
		}
	}
	cout<<ans<<endl;
	return 0;
}

  

打表代码:

# include<iostream>
# include<cstdio>
using namespace std;
# define LL long long
# define uLL unsigned long long

int main()
{
	uLL k=10;
	uLL a=2,b=20;
	int cnt=1;
	while(k<=1000000000000000000)
	{
		cout<<(cnt++)<<' '<<a<<' '<<k<<endl;
		a=a*8+b;
		b*=10;
		k*=10;
	}
	cout<<(cnt++)<<' '<<a<<' '<<k<<endl;
	return 0;
}

  

posted @ 2016-05-06 21:40  20143605  阅读(190)  评论(0编辑  收藏  举报