题目描述
windy定义了一种windy数。
不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。
windy想知道,在A和B之间,包括A和B,总共有多少个windy数。
输入
输入文件包含两个整数,A,B。
输出
输出文件包含一个整数。
样例输入
1 10
样例输出
9
提示
20%的数据,满足1<=A<=B<=1000000
100%的数据,满足1<=A<=B<=2000000000
题解
这题的要注意的是1-9都是算作windy数,所以给最初的pre赋值233,使得这几个数的相邻两位之差必定大于2。然后这题的dfs多了一个判断前导零的参数lead,当前导零存在时也不能return或者更新dp[pos][pre],然后再将约束条件改为当前位和上一位的差值<2时continue即可。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
long long int n,m;
int a[20],dp[20][10];//a用来存放数字的每位数
int dfs(int pos,int pre,bool limit,bool lead)//lead用来表示前导零的情况
{
if(pos==0)
return 1;
if(!limit&&dp[pos][pre]!=-1&&!lead)
return dp[pos][pre];
int ans=0;
int up=limit?a[pos]:9;
for(int i=0;i<=up;i++)
{
if(abs(i-pre)<2)
continue;
int p=i;
if(lead&&i==0)
p=-233;
ans+=dfs(pos-1,p,i==a[pos]&&limit,p==-233);
/*从数字的高位向低位递归,新limit的取值根据原limit和i的取值决定,
例如246,当pos表示十位数时,如果原limit=1(即百位数=2)并且十位数等于4,那么下一次的搜索就会有限制(新limit=1 个位数上界限制为6)*/
}
if(!limit&&!lead)
dp[pos][pre]=ans;
return ans;
}
int solve(int x)
{
int pos=0;//pos用于记录当前位数
while(x)
{
a[++pos]=x%10;//pos从开始表示位数从个位到高位
x/=10;//如在数组中的存放方式是4 2
}
return dfs(pos,-233,1,1);//从数字的最高位开始,pre初始为-233是为了保证只有一位数的数字能够被取到
}
int main()
{
while(cin>>n>>m)
{
memset(dp,-1,sizeof(dp));
cout<<solve(m)-solve(n-1)<<endl;//减的是n-1不是n,n自身要算进去
}
return 0;
}