天天看點

FZU2109 數位dp 含前導零

這題沒考慮到前導0,就是不知道哪wa了,又補題一直wa,scanf和printf改成cin cout就對了 真不知道錯在哪了。。。剛剛又試了一下,G++scanf過不了 但是visual C++可以。真服了,浪費我又一個多小時。

這道題是簡單的數位dp!!!注意前導0!前導0!前導0!掉坑的地方說三遍,順便慶祝下因為前導0,成功爆0。

思路:就是數位dp模闆題,不過置前導0的時候要注意技巧,就是num要放9。為什麼放9呢?因為放9不會限制後面取數。暫且這麼記吧,我真沒整明白為啥放9嗚嗚嗚。

下面是AC代碼!一定要掌握前導0的處理!

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define maxn 20
using namespace std;//這題注意前導0!!! 
int dig[maxn];
ll dp[maxn][maxn][2];

ll dfs(int pos,int num,int odd,int pre0,int limit){
	if(!pos) return 1;
	if(!limit&&dp[pos][num][odd]!=-1) return dp[pos][num][odd];
	int up=limit?dig[pos]:9;
	ll ans=0;
	for(int i=0;i<=up;i++){
		if(pre0==0&&i==0) ans+=dfs(pos-1,9,0,0,limit&&i==up);
		else {
			if(!odd&&i<=num) ans+=dfs(pos-1,i,!odd,pre0||i,limit&&i==up); 
			else if(odd&&i>=num) ans+=dfs(pos-1,i,!odd,pre0||i,limit&&i==up);
		}
	}
	if(!limit) dp[pos][num][odd]=ans;
	return ans;
}
ll solve(ll n){
	int pos=0;
	while(n){
		dig[++pos]=n%10;
		n/=10;
	}
	return dfs(pos,9,0,0,1);
}
int main(){
	int T;
	cin>>T;
	memset(dp,-1,sizeof(dp));
	while(T--){
		ll l,r;
		cin>>l>>r;
		cout<<solve(r)-solve(l-1)<<endl;
	}
	return 0;
}
           

One integer number x is called “Mountain Number” if:

(1) x>0 and x is an integer;

(2) Assume x=a[0]a[1]…a[len-2]a[len-1](0≤a[i]≤9, a[0] is positive). Any a[2i+1] is larger or equal to a[2i] and a[2i+2](if exists).

For example, 111, 132, 893, 7 are “Mountain Number” while 123, 10, 76889 are not “Mountain Number”.

Now you are given L and R, how many “Mountain Number” can be found between L and R (inclusive) ?

Input

The first line of the input contains an integer T (T≤100), indicating the number of test cases.

Then T cases, for any case, only two integers L and R (1≤L≤R≤1,000,000,000).

Output

For each test case, output the number of “Mountain Number” between L and R in a single line.

Sample Input

3

1 10

1 100

1 1000

Sample Output

9

54

384