题目描述 传送门
原来这就是数位DP,原来做过一道类似的。
主要思路就是设
d(i,j)
为最高位为
i
有
我的好像和大多数人的点不一样,似乎写麻烦了…
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
long long d[10][20],sum[20];
int main(){
long long a;
char s1[20],s2[20];
cin>>a;
a--;
sprintf(s1,"%lld",a);
scanf("%s",s2);
int l1=strlen(s1),l2=strlen(s2);
for(int i=0;i<10;i++) d[i][1]=1;
sum[1]=9;
for(int i=2;i<=l2;i++){
for(int j=0;j<=9;j++){
for(int k=0;k<=j-2;k++)
d[j][i]+=d[k][i-1];
for(int k=j+2;k<=9;k++)
d[j][i]+=d[k][i-1];
if(j) sum[i]+=d[j][i];
}
}
int a1=0,a2=0;
for(int i=1;i<=l1-1;i++) a1+=sum[i];
for(int i=1;i<=l2-1;i++) a2+=sum[i];
for(int i=1;i<=s1[0]-'0';i++) a1+=d[i][l1];
for(int i=1;i<=s2[0]-'0';i++) a2+=d[i][l2];
for(int i=l1-1;i>0;i--){
for(int j=s1[l1-i]-'0'+1;j<=9;j++){
if(j>s1[l1-i-1]-2-'0'&&j<s1[l1-i-1]+2-'0') continue;
a1-=d[j][i];
}
if(abs(s1[l1-i]-s1[l1-i-1])<2) break;
}
for(int i=l2-1;i>0;i--){
for(int j=s2[l2-i]-'0'+1;j<=9;j++){
if(j>s2[l2-i-1]-2-'0'&&j<s2[l2-i-1]+2-'0') continue;
a2-=d[j][i];
}
if(abs(s2[l2-i]-s2[l2-i-1])<2) break;
}
cout<<a2-a1<<endl;
return 0;
}