题意: 给定区间, 求该区间的回文数的个数
>> face <<
Strategy: 数位dp dfs数位+滚动数组判回文
状态: dp[i][j][k]代表搜到第i位,起点为j(去前导零+回文判断),k=0:不是回文串反之亦然
目标: s u m [ r ] − s u m [ l − 1 ] ( s u m [ i ] 代 表 1 i 内 的 所 有 合 法 数 的 个 数 ) sum[r]-sum[l-1](sum[i]代表1~i内的所有合法数的个数) sum[r]−sum[l−1](sum[i]代表1 i内的所有合法数的个数)
边界: 没有边界
合法判断: 条件转移合法判断
转移预处理
attention:
双倍经验: 记忆化细节少
上dfs模板, 主要是针对限制条件的变化处理, 判断回文串我们可以先默认是回文的, 边枚举边把数存在temp数组里,然后枚举剩下的判断是否与前面的相契合, 边界是是否是回文串, 如果不是回文串就可以直接跳出来了;
@author: jasonleft 记忆化数位
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define _rep(i, a, b) for (ll i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (ll i = (a); i >= (b); --i)
#define _for(i, a, b) for (ll i = (a); i < (b); ++i)
#define _rof(i, a, b) for (ll i = (a); i > (b); --i)
#define ll long long
#define db double
#define oo 0x3f3f3f3f
#define eps 0.00001
#define all(x) x.begin(), x.end()
#define met(a, b) memset(a, b, sizeof(a))
#define id(x) ((x + 8))
#define bin(x) cerr << #x << " is " << bitset<15>(x) << endl
#define what_is(x) cerr << #x << " is " << x << endl
#define lowbit(x) x &(-x)
using namespace std;
const int maxn = 20;
ll dp[maxn][maxn][2], a[maxn], tmp[maxn], cnt, l, r, cases;
ll dfs(int cur, int start, bool is_palindromic, bool up)
{
if (cur == 0)
return is_palindromic;
if(!is_palindromic)return 0;
ll &t = dp[cur][start][is_palindromic];
if (~t && !up)
return t;
ll ret = 0;
_rep(i, 0, up ? a[cur] : 9)
{
tmp[cur] = i;
if (cur == start && i == 0)
ret += dfs(cur - 1, start - 1, is_palindromic, up && i == a[cur]);
else if (is_palindromic && cur <= (start + 1) >> 1)
ret += dfs(cur - 1, start, i == tmp[start + 1 - cur], up && i == a[cur]);
else
ret += dfs(cur - 1, start, is_palindromic, up && i == a[cur]);
}
if (!up)
t = ret;
return ret;
}
ll ask(ll __)
{
met(a, 0);
cnt = 0;
while (__)
a[++cnt] = __ % 10, __ /= 10;
return dfs(cnt, cnt, 1, 1);
}
signed main()
{
ios::sync_with_stdio(0);
int t;
cin >> t;
met(dp, -1);
while (t--)
{
cin >> l >> r;
if (l > r)
swap(l, r);
cout << "Case " << ++cases << ": " << ask(r) - ask(l - 1) << endl;
}
}