D - windy数(数位dp模板)

windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?

Input
  包含两个整数,A B。

Output
  一个整数

Sample Input
【输入样例一】
1 10
【输入样例二】
25 50
Sample Output
【输出样例一】
9
【输出样例二】
20
Hint
【数据规模和约定】

100%的数据,满足 1 <= A <= B <= 2000000000 。

数位dp,将每个数字分离出来进行记忆化搜索,数位dp保存的时在不同数位的不同状态下所需要的数,以便于下次查询时直接使用,节约大量时间。

对于这题要求没有前导零要仔细思考,要注意前导0是无效的不用管,比如说0001含前导0就可以直接视作1,1001就不含前导0,我们在一开始搜索的时候要把if0标记位1

//#include<bits/stdc++.h>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#define fi first
#define se second
#define FOR(a) for(int i=0;i<a;i++)
#define sc(a) scanf("%d",&a)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = (1<<15)+20;
const ll mod = 1000000007;
const int base = 131;



ll t[N],n,m,dea[20],fin[20],pre[N];
ll shu[100],dp[100][100];

ll dfs(ll len,ll pre,ll limit,ll if0)
{
	if(!len) return 1;
	if(!limit&&dp[len][pre]!=-1&&!if0) return dp[len][pre];
	ll up=limit ? shu[len]: 9;
	ll sum=0;
	for(int i=0;i<=up;i++)
	{
		if((!if0&&abs(i-pre)>=2)||if0)
		sum+=dfs(len-1,i,limit&&i==up,if0&&i==0);
	}
	if(!limit&&!if0) dp[len][pre]=sum;
	return sum;

}
ll solve(int x)
{
	ll cnt=0;
	memset(shu,0,sizeof shu);
	while(x)
	{
		shu[++cnt]=x%10;
		x=x/10;
	}
	dfs(cnt,0,1,1);
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);

	memset(dp,-1,sizeof dp);
	ll l,r;
	while(cin>>n>>m&&(n||m))
	{
		cout<<solve(m)-solve(n-1)<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42640692/article/details/86661277