数字游戏

题目描述

科协里最近很流行数字游戏。某人命名了一种不降数,这种数字必须满足从左到右各位数字成小于等于的关系,如 123,446。现在大家决定玩一个游戏,指定一个整数闭区间\([a,b]\),问这个区间内有多少个不降数。

输入格式

有多组测试数据。每组只含两个数字\(a,b\),意义如题目描述。

输出格式

每行给出一个测试数据的答案,即\([a,b]\)之间有多少不降数。

样例输入

1 9
1 19

样例输出

9
18

Hint

对于全部数据,\(1\leq a \leq b \leq 2^{31}-1\)

思路

数位dp,记录前一位的值即可

Code

/**********************************************************
* @Author: 			   Kirito
* @Date:   			   2020-04-12 17:37:56
* @Last Modified by:   Kirito
* @Last Modified time: 2020-04-12 17:47:00
* @Remark: 
**********************************************************/
#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define CSE(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define Abs(x) (x>=0?x:(-x))
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll , ll> pll;

const int maxn=20;
ll dp[maxn][maxn], digit[maxn];

ll dfs(int pos, int state, bool limit, bool lead)
{
	if(pos == -1) return 1;
	if(!limit && !lead && dp[pos][state] != -1) return dp[pos][state];

	int upbd = limit? digit[pos] : 9;
	int ans = 0;
	for (int i = state; i <= upbd; ++i)
	{
		ans += dfs(pos - 1, i, limit && i == upbd, lead && i == 0);
	}
	if(!limit && !lead) dp[pos][state] = ans;
	return ans;
}

ll get_num(int x)
{
	CSE(dp, -1);
	int pos = 0;
	while(x)
	{
		digit[pos++] = x % 10;
		x /= 10;
	}
	return dfs(pos - 1, 0, true, true);
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	int x, y;
	while(cin >> x >> y)
	{
		cout << get_num(y) - get_num(x - 1) << endl;
	}
	return 0;
}