1. 程式人生 > >101411H Hotel in Ves Lagos 數位DP 2009-2010 ACM-ICPC, NEERC, Western Subregional Contest

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 <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <bitset>
#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) l=mid+1;
		}
		while (solve(mid-1)>=n) mid--;
		while (solve(mid)<n) mid++;
		printf("%lld\n",mid);
	}
	return 0;
}