Gym - 101411H Hotel in Ves Lagos 数位DP 2009-2010 ACM-ICPC, NEERC, Western Subregional Contest

http://codeforces.com/gym/101411/attachments


Problem H. Hotel in Ves Lagos

Input le: hotel.in

Output le: hotel.out

Time limit: 1 second

Memory limit: 256 megabytes

A new hotel is being built in the city of Ves Lagos. The hotel will have an in finite number of rooms(it is out of fashion to build hotels with fi nite numbers of rooms). The new hotel also tries to cater for superstitious guests.

The most common superstition in Ves Lagos is that the number 13 brings bad luck. Accordingly, only numbers whose decimal forms do not contain the substring \13" will be used to label the rooms in the new hotel. For example, the hotel will have rooms numbered 1, 3, 14, 31, 123, but will not have the rooms 13, 132, 913, 1308, 1313.

Let's consider the list of all room numbers, ordered increasingly. Find the N-th number in this list(members of the list are indexed from 1).

Input

The input contains several test cases. 

The 1st line contains T (1 ≤ T ≤ 100), the number of test cases. Each of the following T lines describes one test case and contains the integer N(1 ≤ N ≤ 1018).

Output

The output le should contain exactly T lines, with the i-th line containing exactly one integer, the answer for the i-th test case from the input. 

Example

hotel.in 

3

20

150

1

hotel.out

20

162

1


找到第i个数字中不含有13的数。


与一般的数位DP不同,这题要求找到满足条件的第i个数。

我们只需要二分这个数,求出小于等于这个数的满足条件的数的数量,看何时满足条件。

有个细节需要注意,二分后的数不一定是正确答案。要使solve(k)为题目所给数n,而solve(k-1)为n-1.因为当二分所得的数含有13时,solve该数的值与它之前第一个符合条件的值相等。

这就需要玄学调整答案了。。。


#include 
#include 
#include 
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f; 
int num[20];
ll dp[20][2];

ll dfs(int len,bool pre,bool HaveLimit) {
	if (len==0) return 1;
	if (dp[len][pre]!=-1&&!HaveLimit) 
	    return dp[len][pre];
	
	int l=HaveLimit?num[len]:9;
	ll ans=0;
	for (int i=0;i<=l;i++) {
	    if (i==3&&pre) continue;
	    ans+=dfs(len-1,i==1,HaveLimit&&i==num[len]);
	}
	if (!HaveLimit) dp[len][pre]=ans;
	return ans;
}

ll solve(ll n) {
	ll k=n;
	int i=0;
	while (k) {
		num[++i]=k%10;
		k/=10;
	} 
	ll ans=dfs(i,0,1);
	return ans-1;
}

int main() {
//	freopen("hotel.in","r",stdin);
//	freopen("hotel.out","w",stdout);
	int cas;
	scanf("%d",&cas);
	memset(dp,-1,sizeof(dp));
	while (cas--) {
		ll n,i,l,r,mid;
		scanf("%lld",&n);
		l=1;r=15e17;
		while (l<=r) {
			mid=(l+r)/2;
			ll f=solve(mid);
	//		cout << mid << ' ' << f << endl;
			if (f>=n) r=mid-1; else 
			    if (f=n) mid--;
		while (solve(mid)

你可能感兴趣的:(数位DP)