论数位DP的模板
部分代码适用,有些还是需要改的
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 25; // 位数上限, 10^18 是 19 位
ll dp[N][/*状态维...*/]; // 不含 f, 通常不含 lead
int a[N], len;
ll dfs(int pos, /*状态...,*/ bool lead, bool f) {
if (/*非法状态*/) return 0; // 入口剪枝
if (pos == 0) return /*合法判定*/; // 语义要对
if (!lead && !f && dp[pos][/*状态*/] != -1) // 只在完全自由时读
return dp[pos][/*状态*/];
int up = f ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= up; i++) {
bool nlead = lead && (i == 0);
// 转移: 更新状态, nlead 判前导零, f && (i==up) 传贴界
ans += dfs(pos - 1, /*新状态,*/ nlead, f && (i == up));
}
if (!lead && !f) dp[pos][/*状态*/] = ans; // 只在完全自由时写
return ans;
}
ll solve(ll x) {
if (x <= 0) return 0; // l-1 下溢兜底
len = 0;
while (x) { a[++len] = x % 10; x /= 10; }
// 定长题在此加: if (len < K) return 0;
return dfs(len, /*初始状态,*/ true, true);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
memset(dp, -1, sizeof dp); // 全局清一次, 跨询问复用
int T; cin >> T;
while (T--) {
ll l, r; cin >> l >> r;
cout << solve(r) - solve(l - 1) << '\n';
}
return 0;
}

浙公网安备 33010602011771号