#include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #define maxn 20 long long dp[20][10];//dp[i][j]表示前面一个数为j的i位数的方案数 int bit[20]; long long dfs(int pos,int pre,int f,int lim) //pos当前枚举到的位置,pre记录pos位置前一个位置的数,因为当枚举到pos然后无前导0的时候要拿判断i和前一个数即pre的差是否>=2,如果f为1,即枚举第pos位数时有前导0,此时pre是无意义的。 { int newf,i;//newf用来记录枚举pos-1位置时有没有前导0 int up=lim?bit[pos]:9; if(pos==0) return 1; if(!lim&&(f==0)&&(dp[pos][pre]!=-1)) return dp[pos][pre]; long long ans=0; for(i=0;i<=up;i++) { if(f==1&&i==0) newf=1; else if(f!=1) newf=0; else if(f==1&&i!=0) newf=0; if(f==1)//有前导0的话,pre无效,pow位置的数可以在0~up随便取 { ans+=dfs(pos-1,i,newf,lim&&(i==up)); } else { if(abs(pre-i)>=2) ans+=dfs(pos-1,i,newf,lim&&(i==up)); } } if(!lim&&f==0) dp[pos][pre]=ans;如果是在无限制且无前导0的情况下枚举pos位数的,那么ans可以保留起来以后用 return ans; } long long solve(long long n) { int cnt=0; while(n) { bit[++cnt]=n%10; n/=10; } return dfs(cnt,0,1,1); } int main() { memset(dp,-1,sizeof(dp)); long long l,r; scanf("%lld%lld",&l,&r); printf("%lld\n",solve(r)-solve(l-1)); return 0; }
文章来源: windy数(数位dp)