点击这里查看原题
数位DP,f[i][j]表示以j开头的i位数的个数,cal(x)表示**小于**x的数中符合条件的数的个数,设x=ABCDEFG,长度为len,则答案分为三部分:
- f[len][i] (1<=i<=A-1),非A开头的len位数的个数
- f[i][j] (1<=i<=len-1,1<=j<=9),位数小于len的数的个数
- A开头的数的数的个数
注意要用long long,我因为这个WA了好几次
/*
User:Small
Language:C++
Problem No.:1026
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
ll l,r,f[15][15];
ll cal(ll x){
if(x==0) return 0;
ll res=0,tmp=x,l=0,num[10];
memset(num,0,sizeof(num));
for(;tmp;tmp/=10) num[++l]=tmp%10;
for(int i=1;i<num[l];i++)
res+=f[l][i];
for(int i=l-1;i;i--)
for(int j=1;j<=9;j++) res+=f[i][j];
for(int i=l-1;i;i--){
for(int j=0;j<num[i];j++)
if(abs(j-num[i+1])>1) res+=f[i][j];
if(abs(num[i]-num[i+1])<2) break;
}
return res;
}
int main(){
freopen("data.in","r",stdin);//
for(int i=0;i<10;i++) f[1][i]=1;
for(int i=2;i<=10;i++)
for(int j=0;j<10;j++)
for(int k=0;k<10;k++) if(abs(j-k)>1) f[i][j]+=f[i-1][k];
scanf("%lld%lld",&l,&r);
printf("%lld\n",cal(r+1)-cal(l));
return 0;
}