题意:给定数对(l,r),求([l,r])内不含前导零且相邻两个数字之差至少为2的正整数的个数.(1<=l<=r<= 2000000000.)
直接套模板就好了.因为题目保证了(l>=1)所以可以不特判.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
int len,a[15],dp[15][10];
inline int dfs(int pos,int pre,int lead,int limit){
if(pos>len)return 1;//找到了一个合法的数
if(dp[pos][pre]!=-1&&(!lead)&&(!limit))return dp[pos][pre];//记忆化搜索
int cnt=0,res=limit?a[len-pos+1]:9;
for(int i=0;i<=res;++i){//枚举当前pos位能填的数
if((!i)&&lead)cnt+=dfs(pos+1,0,1,limit&&(i==res));//处理前导零
else if(i&&lead)cnt+=dfs(pos+1,i,0,limit&&(i==res));
else if(abs(i-pre)>=2)cnt+=dfs(pos+1,i,0,limit&&(i==res));//相邻两位数的差的绝对值要大于等于2
}
return (!limit&&!lead)?dp[pos][pre]=cnt:cnt;
}
inline int part(int x){
len=0;
while(x)a[++len]=x%10,x/=10;
memset(dp,-1,sizeof(dp));
dfs(1,0,1,1);
}
int main(){
int l=read(),r=read();
printf("%d
",part(r)-part(l-1));
return 0;
}