不允许前导0的存在 所以先把首位非0的都统计出来 然后在把首位填上非0的数 后面的数就可以自由选择了
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 15;
int d[MAXN+10][MAXN+10], Cur[MAXN+10];
inline int abs(int x) { return x < 0 ? -x : x; }
void init()
{
for(int i = 0; i <= 9; i++) d[1][i] = 1;
for(int i = 2; i <= MAXN; i++)
for(int j = 0; j <= 9; j++)
for(int k = 0; k <= 9; k++)
if(abs(j-k) >= 2)
d[i][j] += d[i-1][k];
}
int solve(int x)
{
int Len = 0, ans = 0;
memset(Cur, 0, sizeof(Cur));
while(x) {
Cur[++Len] = x % 10;
x /= 10;
}
for(int i = 1; i <= Len-1; i++)
for(int j = 1; j <= 9; j++)
ans += d[i][j];
for(int i = 1; i < Cur[Len]; i++) ans += d[Len][i];
for(int i = Len-1; i >= 1; i--)
{
for(int j = 0; j < Cur[i]; j++)
if(abs(j - Cur[i+1]) >= 2)
ans += d[i][j];
if(abs(Cur[i] - Cur[i+1]) < 2) break;
}
return ans;
}
int main()
{
int L, R;
init();
scanf("%d%d", &L, &R);
int ans = solve(R+1) - solve(L);
printf("%d", ans);
}
记忆化搜索版
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#define SF scanf
#define PF printf
using namespace std;
typedef long long LL;
const int MAXN = 15;
int d[MAXN+10][MAXN+10], bit[MAXN+10], tot[MAXN+10];
int f[MAXN+10][MAXN][2][2];
int R, L;
int div(LL x) {
int len = 0;
while(x) {
bit[++len] = x % 10; x /= 10;
}
return len;
}
int dp(int cur, int x, bool lim, bool fir) {
if(cur == 0) return 1;
if(f[cur][x][lim][fir]) return f[cur][x][lim][fir];
int ret = 0, ed = lim ? bit[cur] : 9;
for(int i = 0; i <= ed; i++) {
if(!fir && abs(i-x) < 2) continue;
ret += dp(cur-1, i, lim && i==ed, fir&&i==0);
}
return f[cur][x][lim][fir] = ret;
}
int main() {
SF("%d%d", &L, &R);
int len = div(R), ans = 0;
ans += dp(len, 0, true, true);
len = div(L-1);
ans -= dp(len, 0, true, true);
PF("%d", ans);
}