题面

题目链接

大秦 为你打开 题目传送门

备用题面

将一个数字水平倒置之后,如果和原来一样,那么它就是一个镜像数。

比如 0,1,8,101都是镜像数,而100,3 则不是。

询问区间 $[N,M]$ 里面有多少镜像数。

思路

直接记录我们选择的数字一边递归一边做(因为要保证回文)其他的没什么了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 50;

char a[N], b[N];
ll dp[N][N][2];
char num[N];
int tmp[N];

inline void Input() {
scanf("%s%s", a, b);
}

inline ll Dfs(int cur, int start, int flag, int limit) {
if (cur == -1) return flag;
if (!limit && dp[cur][start][flag] != -1) return dp[cur][start][flag];
ll ans = 0;
int mx = limit ? (num[cur] - 48) : 9;
for (int i = 0; i <= mx; i++) {
if (i != 0 && i != 1 && i != 8) continue;
int st = (cur == start && i == 0);
int newFlag = flag;
if (flag) {
if (!st && cur < (start + 1) / 2) {
newFlag = (tmp[start - cur] == i);
}
}
tmp[cur] = i;
ans += Dfs(
cur - 1,
st ? start - 1 : start,
newFlag,
limit && (i == mx)
);
}
if (!limit) dp[cur][start][flag] = ans;
return ans;
}

inline ll cal(char *s) {
int len = strlen(s);
for (int i = 0; i < len; i++) {
num[i] = s[len - 1 - i];
}
num[len] = 0;
return Dfs(len - 1, len - 1, 1, 1);
}

inline void Work() {
memset(dp, -1, sizeof(dp));
ll ans = cal(b) - cal(a);
int len = strlen(a);
int flag = 1;
for (int i = 0; i < len; i++) {
if ((a[i] != '0' && a[i] != '1' && a[i] != '8') || (a[i] != a[len - 1 - i])) {
flag = 0;
break;
}
}
if (flag) ans++;
printf("%lld\n", ans);
}

int main() {
Input();
Work();
return 0;
}